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.

Conflicts:
        nova/tests/virt/libvirt/test_libvirt.py

NOTE(mriedem): The conflict is due to set_host_enabled
calls which aren't in stable/havana.

Co-Authored-By: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@cloudwatt.com>
Closes-Bug: #1266711
Change-Id: I4ec9ff9a684639ae5b146f400c90115c83afcda7
(cherry picked from commit 85068cc9f6)
tags/2013.2.4
Ken'ichi Ohmichi 5 years ago
parent
commit
6484fc6f0f

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

@@ -636,6 +636,9 @@ class Connection(object):
636 636
     def domainEventRegisterAny(self, dom, eventid, callback, opaque):
637 637
         self._event_callbacks[eventid] = [callback, opaque]
638 638
 
639
+    def registerCloseCallback(self, cb, opaque):
640
+        pass
641
+
639 642
     def getCapabilities(self):
640 643
         """Return spoofed capabilities."""
641 644
         return '''<capabilities>

+ 82
- 16
nova/tests/virt/libvirt/test_libvirt.py View File

@@ -673,8 +673,15 @@ class LibvirtConnTestCase(test.TestCase):
673 673
         self.assertThat(expected, matchers.DictMatches(result))
674 674
 
675 675
     def test_close_callback(self):
676
-        def get_lib_version_stub():
677
-            return (1 * 1000 * 1000) + (0 * 1000) + 1
676
+        class FakeConn(object):
677
+            def getLibVersion(self):
678
+                return (1 * 1000 * 1000) + (0 * 1000) + 1
679
+
680
+            def domainEventRegisterAny(self, *args, **kwargs):
681
+                pass
682
+
683
+            def registerCloseCallback(self, cb, opaque):
684
+                pass
678 685
 
679 686
         self.close_callback = None
680 687
 
@@ -682,26 +689,71 @@ class LibvirtConnTestCase(test.TestCase):
682 689
             self.close_callback = cb
683 690
 
684 691
         conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
685
-        self.stubs.Set(self.conn, "getLibVersion", get_lib_version_stub)
692
+        conn._wrapped_conn = FakeConn()
693
+
686 694
         self.mox.StubOutWithMock(conn, '_connect')
687
-        self.mox.StubOutWithMock(self.conn, 'registerCloseCallback')
688
-
689
-        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(self.conn)
690
-        self.conn.registerCloseCallback(
691
-            mox.IgnoreArg(), mox.IgnoreArg()).WithSideEffects(
692
-                set_close_callback)
693
-        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(self.conn)
694
-        self.conn.registerCloseCallback(mox.IgnoreArg(), mox.IgnoreArg())
695
+        self.mox.StubOutWithMock(conn._conn, 'registerCloseCallback')
696
+
697
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
698
+        conn._conn.registerCloseCallback(
699
+            mox.IgnoreArg(), mox.IgnoreArg()
700
+        ).WithSideEffects(set_close_callback)
701
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
702
+        conn._conn.registerCloseCallback(mox.IgnoreArg(), mox.IgnoreArg())
695 703
         self.mox.ReplayAll()
696 704
 
697 705
         # verify that the driver registers for the close callback
698 706
         # and re-connects after receiving the callback
699
-        conn._get_connection()
707
+        conn._get_new_connection()
700 708
 
701 709
         self.assertTrue(self.close_callback)
702
-        self.close_callback(self.conn, 1, None)
710
+        self.close_callback(conn._conn, 1, None)
703 711
 
704 712
         conn._get_connection()
713
+        self.mox.UnsetStubs()
714
+
715
+    def test_close_callback_bad_signature(self):
716
+        class FakeConn(object):
717
+            def getLibVersion(self):
718
+                return (1 * 1000 * 1000) + (0 * 1000) + 0
719
+
720
+            def domainEventRegisterAny(self, *args, **kwargs):
721
+                pass
722
+
723
+            def registerCloseCallback(self, cb, opaque, *args, **kwargs):
724
+                pass
725
+
726
+        conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
727
+        conn._wrapped_conn = FakeConn()
728
+
729
+        self.mox.StubOutWithMock(conn, '_connect')
730
+        self.mox.StubOutWithMock(conn._conn, 'registerCloseCallback')
731
+
732
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
733
+        conn._conn.registerCloseCallback(
734
+            mox.IgnoreArg(), mox.IgnoreArg()).AndRaise(TypeError)
735
+
736
+        self.mox.ReplayAll()
737
+        conn._get_new_connection()
738
+
739
+    def test_close_callback_not_defined(self):
740
+        class FakeConn():
741
+            def getLibVersion(self):
742
+                return (0 * 1000 * 1000) + (9 * 1000) + 0
743
+
744
+            def domainEventRegisterAny(self, *args, **kwargs):
745
+                pass
746
+
747
+        conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
748
+        conn._wrapped_conn = FakeConn()
749
+
750
+        self.mox.StubOutWithMock(conn, '_connect')
751
+
752
+        conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
753
+            conn._wrapped_conn)
754
+
755
+        self.mox.ReplayAll()
756
+        conn._get_new_connection()
705 757
 
706 758
     def test_get_guest_config(self):
707 759
         conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -7392,12 +7444,26 @@ class LibvirtNonblockingTestCase(test.TestCase):
7392 7444
         jsonutils.to_primitive(connection._conn, convert_instances=True)
7393 7445
 
7394 7446
     def test_tpool_execute_calls_libvirt(self):
7395
-        self.mox.StubOutWithMock(eventlet.tpool, 'execute')
7396 7447
         conn = libvirt.virConnect()
7397 7448
         conn.is_expected = True
7449
+
7450
+        self.mox.StubOutWithMock(eventlet.tpool, 'execute')
7451
+        eventlet.tpool.execute(
7452
+            libvirt.openAuth,
7453
+            'test:///default',
7454
+            mox.IgnoreArg(),
7455
+            mox.IgnoreArg()).AndReturn(conn)
7398 7456
         eventlet.tpool.execute(
7399
-            libvirt.openAuth, 'test:///default',
7400
-            mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn)
7457
+            conn.domainEventRegisterAny,
7458
+            None,
7459
+            libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
7460
+            mox.IgnoreArg(),
7461
+            mox.IgnoreArg())
7462
+        if hasattr(libvirt.virConnect, 'registerCloseCallback'):
7463
+            eventlet.tpool.execute(
7464
+                conn.registerCloseCallback,
7465
+                mox.IgnoreArg(),
7466
+                mox.IgnoreArg())
7401 7467
         self.mox.ReplayAll()
7402 7468
 
7403 7469
         driver = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)

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

@@ -285,7 +285,6 @@ MIN_LIBVIRT_VERSION = (0, 9, 6)
285 285
 # When the above version matches/exceeds this version
286 286
 # delete it & corresponding code using it
287 287
 MIN_LIBVIRT_HOST_CPU_VERSION = (0, 9, 10)
288
-MIN_LIBVIRT_CLOSE_CALLBACK_VERSION = (1, 0, 1)
289 288
 MIN_LIBVIRT_DEVICE_CALLBACK_VERSION = (1, 1, 1)
290 289
 # Live snapshot requirements
291 290
 REQ_HYPERVISOR_LIVESNAPSHOT = "QEMU"
@@ -588,7 +587,7 @@ class LibvirtDriver(driver.ComputeDriver):
588 587
         self._wrapped_conn = wrapped_conn
589 588
 
590 589
         try:
591
-            LOG.debug(_("Registering for lifecycle events %s") % str(self))
590
+            LOG.debug(_("Registering for lifecycle events %s"), self)
592 591
             wrapped_conn.domainEventRegisterAny(
593 592
                 None,
594 593
                 libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE,
@@ -598,17 +597,23 @@ class LibvirtDriver(driver.ComputeDriver):
598 597
             LOG.warn(_("URI %(uri)s does not support events: %(error)s"),
599 598
                      {'uri': self.uri(), 'error': e})
600 599
 
601
-        if self._has_min_version(wrapped_conn,
602
-                                 MIN_LIBVIRT_CLOSE_CALLBACK_VERSION):
603
-            try:
604
-                LOG.debug(_("Registering for connection events: %s") %
605
-                          str(self))
606
-                wrapped_conn.registerCloseCallback(
607
-                        self._close_callback, None)
608
-            except libvirt.libvirtError as e:
609
-                LOG.warn(_("URI %(uri)s does not support connection"
610
-                         " events: %(error)s"),
611
-                         {'uri': self.uri(), 'error': e})
600
+        try:
601
+            LOG.debug(_("Registering for connection events: %s") %
602
+                      str(self))
603
+            wrapped_conn.registerCloseCallback(self._close_callback, None)
604
+        except (TypeError, AttributeError) as e:
605
+            # NOTE: The registerCloseCallback of python-libvirt 1.0.1+
606
+            # is defined with 3 arguments, and the above registerClose-
607
+            # Callback succeeds. However, the one of python-libvirt 1.0.0
608
+            # is defined with 4 arguments and TypeError happens here.
609
+            # Then python-libvirt 0.9 does not define a method register-
610
+            # CloseCallback.
611
+            LOG.debug(_("The version of python-libvirt does not support "
612
+                        "registerCloseCallback or is too old: %s"), e)
613
+        except libvirt.libvirtError as e:
614
+            LOG.warn(_("URI %(uri)s does not support connection"
615
+                       " events: %(error)s"),
616
+                     {'uri': self.uri(), 'error': e})
612 617
 
613 618
         return wrapped_conn
614 619
 

Loading…
Cancel
Save