Browse Source

Fix bug with not implemented virConnect.registerCloseCallback

The unit test test_connection_to_primitive fails many times due to
"virConnect instance has no attribute 'registerCloseCallback'".

registerCloseCallback has been added since original(community's)
python-libvirt v1.0.0, and v1.2.0 also contains the method.
However ubuntu cloud's v1.0.1 does not contain the method, and current
version check of python-libvirt does not work.
This patch tries to operate the method and catch TypeError exception if
the method does not exist instead of the version check.

Co-Authored-By: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@cloudwatt.com>
Closes-Bug: #1266711
Change-Id: I4ec9ff9a684639ae5b146f400c90115c83afcda7
tags/2014.1.b3
Ken'ichi Ohmichi 5 years ago
parent
commit
85068cc9f6

+ 3
- 0
nova/tests/virt/libvirt/fakelibvirt.py View File

@@ -642,6 +642,9 @@ class Connection(object):
642 642
     def domainEventRegisterAny(self, dom, eventid, callback, opaque):
643 643
         self._event_callbacks[eventid] = [callback, opaque]
644 644
 
645
+    def registerCloseCallback(self, cb, opaque):
646
+        pass
647
+
645 648
     def getCapabilities(self):
646 649
         """Return spoofed capabilities."""
647 650
         return '''<capabilities>

+ 78
- 15
nova/tests/virt/libvirt/test_libvirt.py View File

@@ -705,8 +705,15 @@ class LibvirtConnTestCase(test.TestCase):
705 705
         self.assertThat(expected, matchers.DictMatches(result))
706 706
 
707 707
     def test_close_callback(self):
708
-        def get_lib_version_stub():
709
-            return (1 * 1000 * 1000) + (0 * 1000) + 1
708
+        class FakeConn(object):
709
+            def getLibVersion(self):
710
+                return (1 * 1000 * 1000) + (0 * 1000) + 1
711
+
712
+            def domainEventRegisterAny(self, *args, **kwargs):
713
+                pass
714
+
715
+            def registerCloseCallback(self, cb, opaque):
716
+                pass
710 717
 
711 718
         self.close_callback = None
712 719
 
@@ -714,32 +721,80 @@ class LibvirtConnTestCase(test.TestCase):
714 721
             self.close_callback = cb
715 722
 
716 723
         conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
717
-        self.stubs.Set(self.conn, "getLibVersion", get_lib_version_stub)
724
+        conn._wrapped_conn = FakeConn()
725
+
718 726
         self.mox.StubOutWithMock(conn, '_connect')
719
-        self.mox.StubOutWithMock(self.conn, 'registerCloseCallback')
727
+        self.mox.StubOutWithMock(conn._conn, 'registerCloseCallback')
720 728
         self.mox.StubOutWithMock(conn, 'set_host_enabled')
721 729
 
722
-        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(self.conn)
723
-        self.conn.registerCloseCallback(
724
-            mox.IgnoreArg(), mox.IgnoreArg()).WithSideEffects(
725
-                set_close_callback)
730
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
731
+        conn._conn.registerCloseCallback(
732
+            mox.IgnoreArg(), mox.IgnoreArg()
733
+        ).WithSideEffects(set_close_callback)
726 734
         conn.set_host_enabled('fake-mini', True)
727 735
         conn.set_host_enabled('fake-mini', 'Connection to libvirt lost: 1')
728
-        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(self.conn)
736
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
729 737
         conn.set_host_enabled('fake-mini', True)
730
-        self.conn.registerCloseCallback(mox.IgnoreArg(), mox.IgnoreArg())
738
+        conn._conn.registerCloseCallback(mox.IgnoreArg(), mox.IgnoreArg())
731 739
         self.mox.ReplayAll()
732 740
 
733 741
         # verify that the driver registers for the close callback
734 742
         # and re-connects after receiving the callback
735
-        conn._get_connection()
743
+        conn._get_new_connection()
736 744
 
737 745
         self.assertTrue(self.close_callback)
738
-        self.close_callback(self.conn, 1, None)
746
+        self.close_callback(conn._conn, 1, None)
739 747
 
740 748
         conn._get_connection()
741 749
         self.mox.UnsetStubs()
742 750
 
751
+    def test_close_callback_bad_signature(self):
752
+        class FakeConn(object):
753
+            def getLibVersion(self):
754
+                return (1 * 1000 * 1000) + (0 * 1000) + 0
755
+
756
+            def domainEventRegisterAny(self, *args, **kwargs):
757
+                pass
758
+
759
+            def registerCloseCallback(self, cb, opaque, *args, **kwargs):
760
+                pass
761
+
762
+        conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
763
+        conn._wrapped_conn = FakeConn()
764
+
765
+        self.mox.StubOutWithMock(conn, '_connect')
766
+        self.mox.StubOutWithMock(conn._conn, 'registerCloseCallback')
767
+        self.mox.StubOutWithMock(conn, 'set_host_enabled')
768
+
769
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
770
+        conn.set_host_enabled('fake-mini', True)
771
+        conn._conn.registerCloseCallback(
772
+            mox.IgnoreArg(), mox.IgnoreArg()).AndRaise(TypeError)
773
+
774
+        self.mox.ReplayAll()
775
+        conn._get_new_connection()
776
+
777
+    def test_close_callback_not_defined(self):
778
+        class FakeConn():
779
+            def getLibVersion(self):
780
+                return (0 * 1000 * 1000) + (9 * 1000) + 0
781
+
782
+            def domainEventRegisterAny(self, *args, **kwargs):
783
+                pass
784
+
785
+        conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
786
+        conn._wrapped_conn = FakeConn()
787
+
788
+        self.mox.StubOutWithMock(conn, '_connect')
789
+        self.mox.StubOutWithMock(conn, 'set_host_enabled')
790
+
791
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
792
+            conn._wrapped_conn)
793
+        conn.set_host_enabled('fake-mini', True)
794
+
795
+        self.mox.ReplayAll()
796
+        conn._get_new_connection()
797
+
743 798
     def test_cpu_features_bug_1217630(self):
744 799
         conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
745 800
 
@@ -7606,18 +7661,26 @@ class LibvirtNonblockingTestCase(test.TestCase):
7606 7661
         jsonutils.to_primitive(connection._conn, convert_instances=True)
7607 7662
 
7608 7663
     def test_tpool_execute_calls_libvirt(self):
7609
-        self.mox.StubOutWithMock(eventlet.tpool, 'execute')
7610 7664
         conn = libvirt.virConnect()
7611 7665
         conn.is_expected = True
7666
+
7667
+        self.mox.StubOutWithMock(eventlet.tpool, 'execute')
7612 7668
         eventlet.tpool.execute(
7613
-            libvirt.openAuth, 'test:///default',
7614
-            mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn)
7669
+            libvirt.openAuth,
7670
+            'test:///default',
7671
+            mox.IgnoreArg(),
7672
+            mox.IgnoreArg()).AndReturn(conn)
7615 7673
         eventlet.tpool.execute(
7616 7674
             conn.domainEventRegisterAny,
7617 7675
             None,
7618 7676
             libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
7619 7677
             mox.IgnoreArg(),
7620 7678
             mox.IgnoreArg())
7679
+        if hasattr(libvirt.virConnect, 'registerCloseCallback'):
7680
+            eventlet.tpool.execute(
7681
+                conn.registerCloseCallback,
7682
+                mox.IgnoreArg(),
7683
+                mox.IgnoreArg())
7621 7684
         self.mox.ReplayAll()
7622 7685
 
7623 7686
         driver = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)

+ 18
- 13
nova/virt/libvirt/driver.py View File

@@ -323,7 +323,6 @@ MIN_LIBVIRT_VERSION = (0, 9, 6)
323 323
 # When the above version matches/exceeds this version
324 324
 # delete it & corresponding code using it
325 325
 MIN_LIBVIRT_HOST_CPU_VERSION = (0, 9, 10)
326
-MIN_LIBVIRT_CLOSE_CALLBACK_VERSION = (1, 0, 1)
327 326
 MIN_LIBVIRT_DEVICE_CALLBACK_VERSION = (1, 1, 1)
328 327
 # Live snapshot requirements
329 328
 REQ_HYPERVISOR_LIVESNAPSHOT = "QEMU"
@@ -634,7 +633,7 @@ class LibvirtDriver(driver.ComputeDriver):
634 633
         self._wrapped_conn = wrapped_conn
635 634
 
636 635
         try:
637
-            LOG.debug(_("Registering for lifecycle events %s") % str(self))
636
+            LOG.debug(_("Registering for lifecycle events %s"), self)
638 637
             wrapped_conn.domainEventRegisterAny(
639 638
                 None,
640 639
                 libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
@@ -644,17 +643,23 @@ class LibvirtDriver(driver.ComputeDriver):
644 643
             LOG.warn(_("URI %(uri)s does not support events: %(error)s"),
645 644
                      {'uri': self.uri(), 'error': e})
646 645
 
647
-        if self._has_min_version(wrapped_conn,
648
-                                 MIN_LIBVIRT_CLOSE_CALLBACK_VERSION):
649
-            try:
650
-                LOG.debug(_("Registering for connection events: %s") %
651
-                          str(self))
652
-                wrapped_conn.registerCloseCallback(
653
-                        self._close_callback, None)
654
-            except libvirt.libvirtError as e:
655
-                LOG.warn(_("URI %(uri)s does not support connection"
656
-                         " events: %(error)s"),
657
-                         {'uri': self.uri(), 'error': e})
646
+        try:
647
+            LOG.debug(_("Registering for connection events: %s") %
648
+                      str(self))
649
+            wrapped_conn.registerCloseCallback(self._close_callback, None)
650
+        except (TypeError, AttributeError) as e:
651
+            # NOTE: The registerCloseCallback of python-libvirt 1.0.1+
652
+            # is defined with 3 arguments, and the above registerClose-
653
+            # Callback succeeds. However, the one of python-libvirt 1.0.0
654
+            # is defined with 4 arguments and TypeError happens here.
655
+            # Then python-libvirt 0.9 does not define a method register-
656
+            # CloseCallback.
657
+            LOG.debug(_("The version of python-libvirt does not support "
658
+                        "registerCloseCallback or is too old: %s"), e)
659
+        except libvirt.libvirtError as e:
660
+            LOG.warn(_("URI %(uri)s does not support connection"
661
+                       " events: %(error)s"),
662
+                     {'uri': self.uri(), 'error': e})
658 663
 
659 664
         return wrapped_conn
660 665
 

Loading…
Cancel
Save