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

[Libvir] [PATCH] Python bindings now generate exceptions for libvirt errors (third version)



Third version of this patch, which should allow virt-manager to start up correctly*.

virt-manager relies on virDomainGetID returning -1 in the case when a domain is inactive. On further investigation it turns out that virDomainGetID and virDomainGetName can never fail**, since all they do is read fields from the domain pointer that you pass. It was also claimed that virDomainGetUUID was also error-free, but that's actually not the case.

So this patch disables exceptions in those two functions only.

Note that the documentation for virDomainGetID is wrong.

Thanks to Hugh Brock and Dan Berrange for finding and diagnosing the problem.

Rich.

* Not tested: for me virt-manager fails for another reason, with or without this patch.

** Well, they can fail in the case where you've corrupted memory and your virDomainPtr isn't really a virDomainPtr, but at that point all bets are off anyway ...

--
Emerging Technologies, Red Hat  http://et.redhat.com/~rjones/
64 Baker Street, London, W1U 7DF     Mobile: +44 7866 314 421
 "[Negative numbers] darken the very whole doctrines of the equations
 and make dark of the things which are in their nature excessively
 obvious and simple" (Francis Maseres FRS, mathematician, 1759)
Index: python/generator.py
===================================================================
RCS file: /data/cvs/libvirt/python/generator.py,v
retrieving revision 1.18
diff -u -r1.18 generator.py
--- python/generator.py	16 Mar 2007 10:44:44 -0000	1.18
+++ python/generator.py	28 Mar 2007 09:05:25 -0000
@@ -9,6 +9,7 @@
 import os
 import sys
 import string
+import re
 
 if __name__ == "__main__":
     # launched as a script
@@ -561,6 +562,8 @@
 }
 
 functions_noexcept = {
+    'virDomainGetID': True,
+    'virDomainGetName': True,
 }
 
 reference_keepers = {
@@ -575,6 +578,25 @@
     'virNetworkDestroy': "self._o = None",
 }
 
+# Functions returning an integral type which need special rules to
+# check for errors and raise exceptions.
+functions_int_exception_test = {
+    'virDomainGetMaxMemory': "%s == 0",
+}
+functions_int_default_test = "%s == -1"
+
+def is_integral_type (name):
+    return not re.search ("^(unsigned)? ?(int|long)$", name) is None
+
+# Functions returning lists which need special rules to check for errors
+# and raise exceptions.
+functions_list_exception_test = {
+}
+functions_list_default_test = "%s is None"
+
+def is_list_type (name):
+    return name[-1:] == "*"
+
 def nameFixup(name, classe, type, file):
     # avoid a desastrous clash
     listname = classe + "List"
@@ -782,7 +804,8 @@
 		    classes.write("__o");
 		n = n + 1
 	    classes.write(")\n");
-	    if ret[0] != "void":
+
+            if ret[0] != "void":
 		if classes_type.has_key(ret[0]):
 		    #
 		    # Raise an exception
@@ -797,8 +820,35 @@
 		    classes.write("    return ");
 		    classes.write(classes_type[ret[0]][1] % ("ret"));
 		    classes.write("\n");
+
+                # For functions returning an integral type there are
+                # several things that we can do, depending on the
+                # contents of functions_int_*:
+                elif is_integral_type (ret[0]):
+                    if not functions_noexcept.has_key (name):
+                        if functions_int_exception_test.has_key (name):
+                            test = functions_int_exception_test[name]
+                        else:
+                            test = functions_int_default_test
+                        classes.write (("    if " + test +
+                                        ": raise libvirtError ('%s() failed')\n") %
+                                       ("ret", name))
+		    classes.write("    return ret\n")
+
+                elif is_list_type (ret[0]):
+                    if not functions_noexcept.has_key (name):
+                        if functions_list_exception_test.has_key (name):
+                            test = functions_list_exception_test[name]
+                        else:
+                            test = functions_list_default_test
+                        classes.write (("    if " + test +
+                                        ": raise libvirtError ('%s() failed')\n") %
+                                       ("ret", name))
+		    classes.write("    return ret\n")
+
 		else:
-		    classes.write("    return ret\n");
+		    classes.write("    return ret\n")
+
 	    classes.write("\n");
 
     txt.write("\n\n#\n# Set of classes of the module\n#\n\n")
@@ -896,9 +946,9 @@
 			    classes.write(classes_type[arg[1]][0])
 		    n = n + 1
 		classes.write(")\n");
-		if function_post.has_key(name):
-		    classes.write("        %s\n" % (function_post[name]));
-		if ret[0] != "void":
+
+                # For functions returning object types:
+                if ret[0] != "void":
 		    if classes_type.has_key(ret[0]):
 			#
 			# Raise an exception
@@ -911,10 +961,6 @@
                                 classes.write(
 		     "        if ret is None:raise libvirtError('%s() failed', conn=self)\n" %
                                               (name))
-                            elif classname == "virDomain":
-                                classes.write(
-		     "        if ret is None:raise libvirtError('%s() failed')\n" %
-                                              (name))
                             else:
                                 classes.write(
 		     "        if ret is None:raise libvirtError('%s() failed')\n" %
@@ -945,6 +991,12 @@
 				if pref[0] == classname:
 				    classes.write("        __tmp.%s = self\n" %
 						  pref[1])
+
+                        # Post-processing - just before we return.
+                        if function_post.has_key(name):
+                            classes.write("        %s\n" %
+                                          (function_post[name]));
+
 			#
 			# return the class
 			#
@@ -956,11 +1008,71 @@
 			if functions_noexcept.has_key(name):
 			    classes.write(
 			        "        if ret is None:return None");
+
+                        # Post-processing - just before we return.
+                        if function_post.has_key(name):
+                            classes.write("        %s\n" %
+                                          (function_post[name]));
+
 			classes.write("        return ");
 			classes.write(converter_type[ret[0]] % ("ret"));
 			classes.write("\n");
+
+                    # For functions returning an integral type there
+                    # are several things that we can do, depending on
+                    # the contents of functions_int_*:
+                    elif is_integral_type (ret[0]):
+                        if not functions_noexcept.has_key (name):
+                            if functions_int_exception_test.has_key (name):
+                                test = functions_int_exception_test[name]
+                            else:
+                                test = functions_int_default_test
+                            if classname == "virConnect":
+                                classes.write (("        if " + test +
+                                                ": raise libvirtError ('%s() failed', conn=self)\n") %
+                                               ("ret", name))
+                            else:
+                                classes.write (("        if " + test +
+                                                ": raise libvirtError ('%s() failed')\n") %
+                                               ("ret", name))
+
+                        # Post-processing - just before we return.
+                        if function_post.has_key(name):
+                            classes.write("        %s\n" %
+                                          (function_post[name]));
+
+                        classes.write ("        return ret\n")
+
+                    elif is_list_type (ret[0]):
+                        if not functions_noexcept.has_key (name):
+                            if functions_list_exception_test.has_key (name):
+                                test = functions_list_exception_test[name]
+                            else:
+                                test = functions_list_default_test
+                            if classname == "virConnect":
+                                classes.write (("        if " + test +
+                                                ": raise libvirtError ('%s() failed', conn=self)\n") %
+                                               ("ret", name))
+                            else:
+                                classes.write (("        if " + test +
+                                                ": raise libvirtError ('%s() failed')\n") %
+                                               ("ret", name))
+
+                        # Post-processing - just before we return.
+                        if function_post.has_key(name):
+                            classes.write("        %s\n" %
+                                          (function_post[name]));
+
+                        classes.write ("        return ret\n")
+
 		    else:
+                        # Post-processing - just before we return.
+                        if function_post.has_key(name):
+                            classes.write("        %s\n" %
+                                          (function_post[name]));
+
 			classes.write("        return ret\n");
+
 		classes.write("\n");
 
     #

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


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