[Openstack] [OpenStack][Nova] Help with libvirt unit-test - get_diagnostics command

Daniel P. Berrange berrange at redhat.com
Fri Jul 6 12:11:08 UTC 2012


On Fri, Jul 06, 2012 at 11:59:51AM +0100, Leander Bessa Beernaert wrote:
> Hello,
> 
> I've been working on implementing the "diagnostics" command for libvirt -
> https://review.openstack.org/#/c/8839/ . Now i need to create the unit test
> for this new operation. I've been looking at the code to try and figure out
> an easy way to replicate this, but i'm a bit lost.
> 
> What i need to do is simulate a connection to libvirt, create a fake
> instance with a predefined characteristics, retrieve the virtdomain and
> then verify the results from the get_diagnostics command. I'm more at loss
> as to how exactly do i setup a fake connection a create a fake instance? I
> thought about creating a dummy implementation as i've seen being used
> around the tests, however that doesn't give me any access to real method.
> Do note that I'm relatively new to python world, so there's a lot of things
> i can't grasp yes :s.

As you say, figuring out the libvirt Nova test framework is not entirely
easy, particularly if you're new to Python / Nova. So to help you get
your patch through review, here is one suitable test case you can add to
test_libvirt.py for exercising the get_diagnostics API:

diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index eed43b8..f3fa5ff 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -1938,6 +1938,91 @@ class LibvirtConnTestCase(test.TestCase):
         got = jsonutils.loads(conn.get_cpu_info())
         self.assertEqual(want, got)
 
+    def test_diagnostic_full(self):
+        xml = """
+                <domain type='kvm'>
+                    <devices>
+                        <disk type='file'>
+                            <source file='filename'/>
+                            <target dev='vda' bus='virtio'/>
+                        </disk>
+                        <disk type='block'>
+                            <source dev='/path/to/dev/1'/>
+                            <target dev='vdb' bus='virtio'/>
+                        </disk>
+                        <interface type='network'>
+                            <mac address='52:54:00:a4:38:38'/>
+                            <source network='default'/>
+                            <target dev='vnet0'/>
+                        </interface>
+                    </devices>
+                </domain>
+            """
+
+        class DiagFakeDomain(FakeVirtDomain):
+
+            def __init__(self):
+                super(DiagFakeDomain, self).__init__(fake_xml=xml)
+
+            def vcpus(self):
+                return ([(0, 1, 15340000000L, 0),
+                         (1, 1, 1640000000L, 0),
+                         (2, 1, 3040000000L, 0),
+                         (3, 1, 1420000000L, 0)],
+                        [(True, False),
+                         (True, False),
+                         (True, False),
+                         (True, False)])
+
+            def blockStats(self, path):
+                return (169L, 688640L, 0L, 0L, -1L)
+
+            def interfaceStats(self, path):
+                return (4408L, 82L, 0L, 0L, 0L, 0L, 0L, 0L)
+
+            def memoryStats(self):
+                return {'actual': 220160L, 'rss': 200164L}
+
+            def maxMemory(self):
+                return 280160L
+
+        def fake_lookup_name(name):
+            return DiagFakeDomain()
+
+        self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
+        libvirt_driver.LibvirtDriver._conn.lookupByName = fake_lookup_name
+
+        conn = libvirt_driver.LibvirtDriver(False)
+        actual = conn.get_diagnostics( { "name": "testvirt" })
+        expect = {'cpu0_time': 15340000000L,
+                  'cpu1_time': 1640000000L,
+                  'cpu2_time': 3040000000L,
+                  'cpu3_time': 1420000000L,
+                  'vda_read': 688640L,
+                  'vda_read_req': 169L,
+                  'vda_write': 0L,
+                  'vda_write_req': 0L,
+                  'vda_errors': -1L,
+                  'vdb_read': 688640L,
+                  'vdb_read_req': 169L,
+                  'vdb_write': 0L,
+                  'vdb_write_req': 0L,
+                  'vdb_errors': -1L,
+                  'memory': 280160L,
+                  'memory-actual': 220160L,
+                  'memory-rss': 200164L,
+                  'vnet0_rx': 4408L,
+                  'vnet0_rx_drop': 0L,
+                  'vnet0_rx_errors': 0L,
+                  'vnet0_rx_packets': 82L,
+                  'vnet0_tx': 0L,
+                  'vnet0_tx_drop': 0L,
+                  'vnet0_tx_errors': 0L,
+                  'vnet0_tx_packets': 0L,
+                  }
+
+        self.assertEqual(actual, expect)
+
 
 class HostStateTestCase(test.TestCase):


A description of what I'm doing here:

 * First we mock up an XML document that describes our test
   guest, with 2 disks and 1 NIC.

 * We create the FakeVirtDomain() class which provides a stub
   implementation of the various libvirt APIs that the
   get_diagnostics method will call.

 * The fake APIs will return a hardcoded set of statistics

 * We use StubOutWithMock() to make sure that the libvirt connection
   returns an instance of our FakeVirtDomain class

 * Finally we can call the get_diagnostics() method, and compare
   the data it returns against what we want.


Now this test case only tests the "normal" operation of the API. As noted
in the review comments, it is possible for the methods like 'vcpus',
'intefaceStats', 'blockStats', etc to raise libvirt exceptions. So in
addition to what I've shown here, you will also want to add some more
test cases, which verify that exception handling works correctly.

To do this, just copy my example test case above, and make some small
changes.  eg change the impl of 'vcpus' to be this:

   def vcps():
      raise libvirtException("fake failure")

and then remove the 'cpuN_time' elements from the 'expected' data hash

and similarly for the interfaceStats/blockStats/memoryStats methods
which can also raise errors.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the Openstack mailing list