"Fossies" - the Fresh Open Source Software Archive

Member "nova-22.0.1/nova/tests/unit/virt/libvirt/test_host.py" (19 Nov 2020, 58049 Bytes) of package /linux/misc/openstack/nova-22.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_host.py": 22.0.0_vs_22.0.1.

    1 #    Copyright 2010 OpenStack Foundation
    2 #    Copyright 2012 University Of Minho
    3 #    Copyright 2014 Red Hat, Inc
    4 #
    5 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    6 #    not use this file except in compliance with the License. You may obtain
    7 #    a copy of the License at
    8 #
    9 #         http://www.apache.org/licenses/LICENSE-2.0
   10 #
   11 #    Unless required by applicable law or agreed to in writing, software
   12 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   13 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   14 #    License for the specific language governing permissions and limitations
   15 #    under the License.
   16 
   17 import os
   18 
   19 import eventlet
   20 from eventlet import greenthread
   21 from eventlet import tpool
   22 import mock
   23 from oslo_utils.fixture import uuidsentinel as uuids
   24 from oslo_utils import uuidutils
   25 import six
   26 from six.moves import builtins
   27 import testtools
   28 
   29 
   30 from nova.compute import vm_states
   31 from nova import exception
   32 from nova import objects
   33 from nova.objects import fields as obj_fields
   34 from nova import test
   35 from nova.tests.unit.virt.libvirt import fake_libvirt_data
   36 from nova.tests.unit.virt.libvirt import fakelibvirt
   37 from nova.virt import event
   38 from nova.virt.libvirt import config as vconfig
   39 from nova.virt.libvirt import driver as libvirt_driver
   40 from nova.virt.libvirt import guest as libvirt_guest
   41 from nova.virt.libvirt import host
   42 
   43 
   44 class StringMatcher(object):
   45     def __eq__(self, other):
   46         return isinstance(other, six.string_types)
   47 
   48 
   49 class FakeVirtDomain(object):
   50 
   51     def __init__(self, id=-1, name=None):
   52         self._id = id
   53         self._name = name
   54         self._uuid = uuidutils.generate_uuid()
   55 
   56     def name(self):
   57         return self._name
   58 
   59     def ID(self):
   60         return self._id
   61 
   62     def UUIDString(self):
   63         return self._uuid
   64 
   65 
   66 class HostTestCase(test.NoDBTestCase):
   67 
   68     def setUp(self):
   69         super(HostTestCase, self).setUp()
   70 
   71         self.useFixture(fakelibvirt.FakeLibvirtFixture())
   72         self.host = host.Host("qemu:///system")
   73 
   74     @mock.patch("nova.virt.libvirt.host.Host._init_events")
   75     def test_repeat_initialization(self, mock_init_events):
   76         for i in range(3):
   77             self.host.initialize()
   78         mock_init_events.assert_called_once_with()
   79 
   80     @mock.patch.object(fakelibvirt.virConnect, "registerCloseCallback")
   81     def test_close_callback(self, mock_close):
   82         self.close_callback = None
   83 
   84         def set_close_callback(cb, opaque):
   85             self.close_callback = cb
   86 
   87         mock_close.side_effect = set_close_callback
   88         # verify that the driver registers for the close callback
   89         self.host.get_connection()
   90         self.assertTrue(self.close_callback)
   91 
   92     @mock.patch.object(fakelibvirt.virConnect, "getLibVersion")
   93     def test_broken_connection(self, mock_ver):
   94         for (error, domain) in (
   95                 (fakelibvirt.VIR_ERR_SYSTEM_ERROR,
   96                  fakelibvirt.VIR_FROM_REMOTE),
   97                 (fakelibvirt.VIR_ERR_SYSTEM_ERROR,
   98                  fakelibvirt.VIR_FROM_RPC),
   99                 (fakelibvirt.VIR_ERR_INTERNAL_ERROR,
  100                  fakelibvirt.VIR_FROM_RPC)):
  101 
  102             conn = self.host._connect("qemu:///system", False)
  103             mock_ver.side_effect = fakelibvirt.make_libvirtError(
  104                 fakelibvirt.libvirtError,
  105                 "Connection broken",
  106                 error_code=error,
  107                 error_domain=domain)
  108             self.assertFalse(self.host._test_connection(conn))
  109 
  110     @mock.patch.object(host, 'LOG')
  111     def test_connect_auth_cb_exception(self, log_mock):
  112         creds = dict(authname='nova', password='verybadpass')
  113         self.assertRaises(exception.NovaException,
  114                           self.host._connect_auth_cb, creds, False)
  115         self.assertEqual(0, len(log_mock.method_calls),
  116                          'LOG should not be used in _connect_auth_cb.')
  117 
  118     @mock.patch.object(greenthread, 'spawn_after')
  119     def test_event_dispatch(self, mock_spawn_after):
  120         # Validate that the libvirt self-pipe for forwarding
  121         # events between threads is working sanely
  122         def handler(event):
  123             got_events.append(event)
  124 
  125         hostimpl = host.Host("qemu:///system",
  126                              lifecycle_event_handler=handler)
  127         got_events = []
  128 
  129         hostimpl._init_events_pipe()
  130 
  131         event1 = event.LifecycleEvent(
  132             "cef19ce0-0ca2-11df-855d-b19fbce37686",
  133             event.EVENT_LIFECYCLE_STARTED)
  134         event2 = event.LifecycleEvent(
  135             "cef19ce0-0ca2-11df-855d-b19fbce37686",
  136             event.EVENT_LIFECYCLE_PAUSED)
  137         hostimpl._queue_event(event1)
  138         hostimpl._queue_event(event2)
  139         hostimpl._dispatch_events()
  140 
  141         want_events = [event1, event2]
  142         self.assertEqual(want_events, got_events)
  143 
  144         event3 = event.LifecycleEvent(
  145             "cef19ce0-0ca2-11df-855d-b19fbce37686",
  146             event.EVENT_LIFECYCLE_RESUMED)
  147         event4 = event.LifecycleEvent(
  148             "cef19ce0-0ca2-11df-855d-b19fbce37686",
  149             event.EVENT_LIFECYCLE_STOPPED)
  150 
  151         hostimpl._queue_event(event3)
  152         hostimpl._queue_event(event4)
  153         hostimpl._dispatch_events()
  154 
  155         want_events = [event1, event2, event3]
  156         self.assertEqual(want_events, got_events)
  157 
  158         # STOPPED is delayed so it's handled separately
  159         mock_spawn_after.assert_called_once_with(
  160             hostimpl._lifecycle_delay, hostimpl._event_emit, event4)
  161 
  162     def test_event_lifecycle(self):
  163         got_events = []
  164 
  165         # Validate that libvirt events are correctly translated
  166         # to Nova events
  167         def spawn_after(seconds, func, *args, **kwargs):
  168             got_events.append(args[0])
  169             return mock.Mock(spec=greenthread.GreenThread)
  170 
  171         greenthread.spawn_after = mock.Mock(side_effect=spawn_after)
  172         hostimpl = host.Host("qemu:///system",
  173                              lifecycle_event_handler=lambda e: None)
  174         conn = hostimpl.get_connection()
  175 
  176         hostimpl._init_events_pipe()
  177         fake_dom_xml = """
  178                 <domain type='kvm'>
  179                   <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
  180                   <devices>
  181                     <disk type='file'>
  182                       <source file='filename'/>
  183                     </disk>
  184                   </devices>
  185                 </domain>
  186             """
  187         dom = fakelibvirt.Domain(conn,
  188                                  fake_dom_xml,
  189                                  False)
  190 
  191         hostimpl._event_lifecycle_callback(
  192             conn, dom, fakelibvirt.VIR_DOMAIN_EVENT_STOPPED, 0, hostimpl)
  193         hostimpl._dispatch_events()
  194         self.assertEqual(len(got_events), 1)
  195         self.assertIsInstance(got_events[0], event.LifecycleEvent)
  196         self.assertEqual(got_events[0].uuid,
  197                          "cef19ce0-0ca2-11df-855d-b19fbce37686")
  198         self.assertEqual(got_events[0].transition,
  199                          event.EVENT_LIFECYCLE_STOPPED)
  200 
  201     def test_event_lifecycle_callback_suspended_postcopy(self):
  202         """Tests the suspended lifecycle event with libvirt with post-copy"""
  203         hostimpl = mock.MagicMock()
  204         conn = mock.MagicMock()
  205         fake_dom_xml = """
  206                 <domain type='kvm'>
  207                   <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
  208                 </domain>
  209             """
  210         dom = fakelibvirt.Domain(conn, fake_dom_xml, running=True)
  211         host.Host._event_lifecycle_callback(
  212             conn, dom, fakelibvirt.VIR_DOMAIN_EVENT_SUSPENDED,
  213             detail=fakelibvirt.VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY,
  214             opaque=hostimpl)
  215         expected_event = hostimpl._queue_event.call_args[0][0]
  216         self.assertEqual(event.EVENT_LIFECYCLE_POSTCOPY_STARTED,
  217                          expected_event.transition)
  218 
  219     @mock.patch('nova.virt.libvirt.guest.Guest.get_job_info')
  220     def test_event_lifecycle_callback_suspended_migrated(self, get_job_info):
  221         """Tests the suspended lifecycle event with libvirt with migrated"""
  222         hostimpl = mock.MagicMock()
  223         conn = mock.MagicMock()
  224         fake_dom_xml = """
  225                 <domain type='kvm'>
  226                   <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
  227                 </domain>
  228             """
  229         dom = fakelibvirt.Domain(conn, fake_dom_xml, running=True)
  230         jobinfo = libvirt_guest.JobInfo(
  231             type=fakelibvirt.VIR_DOMAIN_JOB_COMPLETED)
  232         get_job_info.return_value = jobinfo
  233         host.Host._event_lifecycle_callback(
  234             conn, dom, fakelibvirt.VIR_DOMAIN_EVENT_SUSPENDED,
  235             detail=fakelibvirt.VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED,
  236             opaque=hostimpl)
  237         expected_event = hostimpl._queue_event.call_args[0][0]
  238         self.assertEqual(event.EVENT_LIFECYCLE_MIGRATION_COMPLETED,
  239                          expected_event.transition)
  240         get_job_info.assert_called_once_with()
  241 
  242     @mock.patch('nova.virt.libvirt.guest.Guest.get_job_info')
  243     @mock.patch('nova.virt.libvirt.migration.find_job_type')
  244     def test_event_lifecycle_callback_suspended_migrated_job_failed(
  245             self, find_job_type, get_job_info):
  246         """Tests the suspended lifecycle event with libvirt with migrated"""
  247         hostimpl = mock.MagicMock()
  248         conn = mock.MagicMock()
  249         fake_dom_xml = """
  250                 <domain type='kvm'>
  251                   <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
  252                 </domain>
  253             """
  254         dom = fakelibvirt.Domain(conn, fake_dom_xml, running=True)
  255         jobinfo = libvirt_guest.JobInfo(type=fakelibvirt.VIR_DOMAIN_JOB_NONE)
  256         get_job_info.return_value = jobinfo
  257         # If the job type is VIR_DOMAIN_JOB_NONE we'll attempt to figure out
  258         # the actual job status, so in this case we mock it to be a failure.
  259         find_job_type.return_value = fakelibvirt.VIR_DOMAIN_JOB_FAILED
  260         host.Host._event_lifecycle_callback(
  261             conn, dom, fakelibvirt.VIR_DOMAIN_EVENT_SUSPENDED,
  262             detail=fakelibvirt.VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED,
  263             opaque=hostimpl)
  264         expected_event = hostimpl._queue_event.call_args[0][0]
  265         self.assertEqual(event.EVENT_LIFECYCLE_PAUSED,
  266                          expected_event.transition)
  267         get_job_info.assert_called_once_with()
  268         find_job_type.assert_called_once_with(
  269             test.MatchType(libvirt_guest.Guest), instance=None,
  270             logging_ok=False)
  271 
  272     def test_event_emit_delayed_call_delayed(self):
  273         ev = event.LifecycleEvent(
  274             "cef19ce0-0ca2-11df-855d-b19fbce37686",
  275             event.EVENT_LIFECYCLE_STOPPED)
  276         for uri in ("qemu:///system", "xen:///"):
  277             spawn_after_mock = mock.Mock()
  278             greenthread.spawn_after = spawn_after_mock
  279             hostimpl = host.Host(uri,
  280                                  lifecycle_event_handler=lambda e: None)
  281             hostimpl._event_emit_delayed(ev)
  282             spawn_after_mock.assert_called_once_with(
  283                 15, hostimpl._event_emit, ev)
  284 
  285     @mock.patch.object(greenthread, 'spawn_after')
  286     def test_event_emit_delayed_call_delayed_pending(self, spawn_after_mock):
  287         hostimpl = host.Host("xen:///",
  288                              lifecycle_event_handler=lambda e: None)
  289 
  290         uuid = "cef19ce0-0ca2-11df-855d-b19fbce37686"
  291         gt_mock = mock.Mock()
  292         hostimpl._events_delayed[uuid] = gt_mock
  293         ev = event.LifecycleEvent(
  294             uuid, event.EVENT_LIFECYCLE_STOPPED)
  295         hostimpl._event_emit_delayed(ev)
  296         gt_mock.cancel.assert_called_once_with()
  297         self.assertTrue(spawn_after_mock.called)
  298 
  299     def test_event_delayed_cleanup(self):
  300         hostimpl = host.Host("xen:///",
  301                              lifecycle_event_handler=lambda e: None)
  302         uuid = "cef19ce0-0ca2-11df-855d-b19fbce37686"
  303         ev = event.LifecycleEvent(
  304             uuid, event.EVENT_LIFECYCLE_STARTED)
  305         gt_mock = mock.Mock()
  306         hostimpl._events_delayed[uuid] = gt_mock
  307         hostimpl._event_emit_delayed(ev)
  308         gt_mock.cancel.assert_called_once_with()
  309         self.assertNotIn(uuid, hostimpl._events_delayed.keys())
  310 
  311     @mock.patch.object(fakelibvirt.virConnect, "domainEventRegisterAny")
  312     @mock.patch.object(host.Host, "_connect")
  313     def test_get_connection_serial(self, mock_conn, mock_event):
  314         def get_conn_currency(host):
  315             host.get_connection().getLibVersion()
  316 
  317         def connect_with_block(*a, **k):
  318             # enough to allow another connect to run
  319             eventlet.sleep(0)
  320             self.connect_calls += 1
  321             return fakelibvirt.openAuth("qemu:///system",
  322                                         [[], lambda: 1, None], 0)
  323 
  324         def fake_register(*a, **k):
  325             self.register_calls += 1
  326 
  327         self.connect_calls = 0
  328         self.register_calls = 0
  329 
  330         mock_conn.side_effect = connect_with_block
  331         mock_event.side_effect = fake_register
  332 
  333         # call serially
  334         get_conn_currency(self.host)
  335         get_conn_currency(self.host)
  336         self.assertEqual(self.connect_calls, 1)
  337         self.assertEqual(self.register_calls, 1)
  338 
  339     @mock.patch.object(fakelibvirt.virConnect, "domainEventRegisterAny")
  340     @mock.patch.object(host.Host, "_connect")
  341     def test_get_connection_concurrency(self, mock_conn, mock_event):
  342         def get_conn_currency(host):
  343             host.get_connection().getLibVersion()
  344 
  345         def connect_with_block(*a, **k):
  346             # enough to allow another connect to run
  347             eventlet.sleep(0)
  348             self.connect_calls += 1
  349             return fakelibvirt.openAuth("qemu:///system",
  350                                         [[], lambda: 1, None], 0)
  351 
  352         def fake_register(*a, **k):
  353             self.register_calls += 1
  354 
  355         self.connect_calls = 0
  356         self.register_calls = 0
  357 
  358         mock_conn.side_effect = connect_with_block
  359         mock_event.side_effect = fake_register
  360 
  361         # call concurrently
  362         thr1 = eventlet.spawn(get_conn_currency, self.host)
  363         thr2 = eventlet.spawn(get_conn_currency, self.host)
  364 
  365         # let threads run
  366         eventlet.sleep(0)
  367 
  368         thr1.wait()
  369         thr2.wait()
  370         self.assertEqual(self.connect_calls, 1)
  371         self.assertEqual(self.register_calls, 1)
  372 
  373     @mock.patch.object(host.Host, "_connect")
  374     def test_conn_event(self, mock_conn):
  375         handler = mock.MagicMock()
  376         h = host.Host("qemu:///system", conn_event_handler=handler)
  377 
  378         h.get_connection()
  379         h._dispatch_conn_event()
  380 
  381         handler.assert_called_once_with(True, None)
  382 
  383     @mock.patch.object(host.Host, "_connect")
  384     def test_conn_event_fail(self, mock_conn):
  385         handler = mock.MagicMock()
  386         h = host.Host("qemu:///system", conn_event_handler=handler)
  387         mock_conn.side_effect = fakelibvirt.libvirtError('test')
  388 
  389         self.assertRaises(exception.HypervisorUnavailable, h.get_connection)
  390         h._dispatch_conn_event()
  391 
  392         handler.assert_called_once_with(False, StringMatcher())
  393 
  394         # Attempt to get a second connection, and assert that we don't add
  395         # queue a second callback. Note that we can't call
  396         # _dispatch_conn_event() and assert no additional call to the handler
  397         # here as above. This is because we haven't added an event, so it would
  398         # block. We mock the helper method which queues an event for callback
  399         # instead.
  400         with mock.patch.object(h, '_queue_conn_event_handler') as mock_queue:
  401             self.assertRaises(exception.HypervisorUnavailable,
  402                               h.get_connection)
  403             mock_queue.assert_not_called()
  404 
  405     @mock.patch.object(host.Host, "_test_connection")
  406     @mock.patch.object(host.Host, "_connect")
  407     def test_conn_event_up_down(self, mock_conn, mock_test_conn):
  408         handler = mock.MagicMock()
  409         h = host.Host("qemu:///system", conn_event_handler=handler)
  410         mock_conn.side_effect = (mock.MagicMock(),
  411                                  fakelibvirt.libvirtError('test'))
  412         mock_test_conn.return_value = False
  413 
  414         h.get_connection()
  415         self.assertRaises(exception.HypervisorUnavailable, h.get_connection)
  416         h._dispatch_conn_event()
  417         h._dispatch_conn_event()
  418 
  419         handler.assert_has_calls([
  420             mock.call(True, None),
  421             mock.call(False, StringMatcher())
  422         ])
  423 
  424     @mock.patch.object(host.Host, "_connect")
  425     def test_conn_event_thread(self, mock_conn):
  426         event = eventlet.event.Event()
  427         h = host.Host("qemu:///system", conn_event_handler=event.send)
  428         h.initialize()
  429 
  430         h.get_connection()
  431         event.wait()
  432         # This test will timeout if it fails. Success is implicit in a
  433         # timely return from wait(), indicating that the connection event
  434         # handler was called.
  435 
  436     @mock.patch.object(fakelibvirt.virConnect, "getLibVersion")
  437     @mock.patch.object(fakelibvirt.virConnect, "getVersion")
  438     @mock.patch.object(fakelibvirt.virConnect, "getType")
  439     def test_has_min_version(self, fake_hv_type, fake_hv_ver, fake_lv_ver):
  440         fake_lv_ver.return_value = 1002003
  441         fake_hv_ver.return_value = 4005006
  442         fake_hv_type.return_value = 'xyz'
  443 
  444         lv_ver = (1, 2, 3)
  445         hv_ver = (4, 5, 6)
  446         hv_type = 'xyz'
  447         self.assertTrue(self.host.has_min_version(lv_ver, hv_ver, hv_type))
  448 
  449         self.assertFalse(self.host.has_min_version(lv_ver, hv_ver, 'abc'))
  450         self.assertFalse(self.host.has_min_version(lv_ver, (4, 5, 7), hv_type))
  451         self.assertFalse(self.host.has_min_version((1, 3, 3), hv_ver, hv_type))
  452 
  453         self.assertTrue(self.host.has_min_version(lv_ver, hv_ver, None))
  454         self.assertTrue(self.host.has_min_version(lv_ver, None, hv_type))
  455         self.assertTrue(self.host.has_min_version(None, hv_ver, hv_type))
  456 
  457     @mock.patch.object(fakelibvirt.virConnect, "getLibVersion")
  458     @mock.patch.object(fakelibvirt.virConnect, "getVersion")
  459     @mock.patch.object(fakelibvirt.virConnect, "getType")
  460     def test_has_version(self, fake_hv_type, fake_hv_ver, fake_lv_ver):
  461         fake_lv_ver.return_value = 1002003
  462         fake_hv_ver.return_value = 4005006
  463         fake_hv_type.return_value = 'xyz'
  464 
  465         lv_ver = (1, 2, 3)
  466         hv_ver = (4, 5, 6)
  467         hv_type = 'xyz'
  468         self.assertTrue(self.host.has_version(lv_ver, hv_ver, hv_type))
  469 
  470         for lv_ver_ in [(1, 2, 2), (1, 2, 4)]:
  471             self.assertFalse(self.host.has_version(lv_ver_, hv_ver, hv_type))
  472         for hv_ver_ in [(4, 4, 6), (4, 6, 6)]:
  473             self.assertFalse(self.host.has_version(lv_ver, hv_ver_, hv_type))
  474         self.assertFalse(self.host.has_version(lv_ver, hv_ver, 'abc'))
  475 
  476         self.assertTrue(self.host.has_version(lv_ver, hv_ver, None))
  477         self.assertTrue(self.host.has_version(lv_ver, None, hv_type))
  478         self.assertTrue(self.host.has_version(None, hv_ver, hv_type))
  479 
  480     @mock.patch.object(fakelibvirt.virConnect, "lookupByUUIDString")
  481     def test_get_domain(self, fake_lookup):
  482         uuid = uuidutils.generate_uuid()
  483         dom = fakelibvirt.virDomain(self.host.get_connection(),
  484                                     "<domain id='7'/>")
  485         instance = objects.Instance(id="124", uuid=uuid)
  486         fake_lookup.return_value = dom
  487 
  488         self.assertEqual(dom, self.host._get_domain(instance))
  489         fake_lookup.assert_called_once_with(uuid)
  490 
  491     @mock.patch.object(fakelibvirt.virConnect, "lookupByUUIDString")
  492     def test_get_domain_raises(self, fake_lookup):
  493         instance = objects.Instance(uuid=uuids.instance,
  494                                     vm_state=vm_states.ACTIVE)
  495         fake_lookup.side_effect = fakelibvirt.make_libvirtError(
  496             fakelibvirt.libvirtError,
  497             'Domain not found: no domain with matching name',
  498             error_code=fakelibvirt.VIR_ERR_NO_DOMAIN,
  499             error_domain=fakelibvirt.VIR_FROM_QEMU)
  500 
  501         with testtools.ExpectedException(exception.InstanceNotFound):
  502             self.host._get_domain(instance)
  503 
  504         fake_lookup.assert_called_once_with(uuids.instance)
  505 
  506     @mock.patch.object(fakelibvirt.virConnect, "lookupByUUIDString")
  507     def test_get_guest(self, fake_lookup):
  508         uuid = uuidutils.generate_uuid()
  509         dom = fakelibvirt.virDomain(self.host.get_connection(),
  510                                     "<domain id='7'/>")
  511 
  512         fake_lookup.return_value = dom
  513         instance = objects.Instance(id="124", uuid=uuid)
  514 
  515         guest = self.host.get_guest(instance)
  516         self.assertEqual(dom, guest._domain)
  517         self.assertIsInstance(guest, libvirt_guest.Guest)
  518 
  519         fake_lookup.assert_called_once_with(uuid)
  520 
  521     @mock.patch.object(fakelibvirt.Connection, "listAllDomains")
  522     def test_list_instance_domains(self, mock_list_all):
  523         vm0 = FakeVirtDomain(id=0, name="Domain-0")  # Xen dom-0
  524         vm1 = FakeVirtDomain(id=3, name="instance00000001")
  525         vm2 = FakeVirtDomain(id=17, name="instance00000002")
  526         vm3 = FakeVirtDomain(name="instance00000003")
  527         vm4 = FakeVirtDomain(name="instance00000004")
  528 
  529         def fake_list_all(flags):
  530             vms = [vm0]
  531             if flags & fakelibvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE:
  532                 vms.extend([vm1, vm2])
  533             if flags & fakelibvirt.VIR_CONNECT_LIST_DOMAINS_INACTIVE:
  534                 vms.extend([vm3, vm4])
  535             return vms
  536 
  537         mock_list_all.side_effect = fake_list_all
  538 
  539         doms = self.host.list_instance_domains()
  540 
  541         mock_list_all.assert_called_once_with(
  542             fakelibvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE)
  543         mock_list_all.reset_mock()
  544 
  545         self.assertEqual(len(doms), 2)
  546         self.assertEqual(doms[0].name(), vm1.name())
  547         self.assertEqual(doms[1].name(), vm2.name())
  548 
  549         doms = self.host.list_instance_domains(only_running=False)
  550 
  551         mock_list_all.assert_called_once_with(
  552             fakelibvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE |
  553             fakelibvirt.VIR_CONNECT_LIST_DOMAINS_INACTIVE)
  554         mock_list_all.reset_mock()
  555 
  556         self.assertEqual(len(doms), 4)
  557         self.assertEqual(doms[0].name(), vm1.name())
  558         self.assertEqual(doms[1].name(), vm2.name())
  559         self.assertEqual(doms[2].name(), vm3.name())
  560         self.assertEqual(doms[3].name(), vm4.name())
  561 
  562         doms = self.host.list_instance_domains(only_guests=False)
  563 
  564         mock_list_all.assert_called_once_with(
  565             fakelibvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE)
  566         mock_list_all.reset_mock()
  567 
  568         self.assertEqual(len(doms), 3)
  569         self.assertEqual(doms[0].name(), vm0.name())
  570         self.assertEqual(doms[1].name(), vm1.name())
  571         self.assertEqual(doms[2].name(), vm2.name())
  572 
  573     @mock.patch.object(host.Host, "list_instance_domains")
  574     def test_list_guests(self, mock_list_domains):
  575         dom0 = mock.Mock(spec=fakelibvirt.virDomain)
  576         dom1 = mock.Mock(spec=fakelibvirt.virDomain)
  577         mock_list_domains.return_value = [
  578             dom0, dom1]
  579         result = self.host.list_guests(True, False)
  580         mock_list_domains.assert_called_once_with(
  581             only_running=True, only_guests=False)
  582         self.assertEqual(dom0, result[0]._domain)
  583         self.assertEqual(dom1, result[1]._domain)
  584 
  585     def test_cpu_features_bug_1217630(self):
  586         self.host.get_connection()
  587 
  588         # Test old version of libvirt, it shouldn't see the `aes' feature
  589         with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
  590             del mock_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
  591             caps = self.host.get_capabilities()
  592             self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
  593 
  594         # Cleanup the capabilities cache firstly
  595         self.host._caps = None
  596 
  597         # Test new version of libvirt, should find the `aes' feature
  598         with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
  599             mock_libvirt['VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'] = 1
  600             caps = self.host.get_capabilities()
  601             self.assertIn('aes', [x.name for x in caps.host.cpu.features])
  602 
  603     def test_cpu_features_are_not_duplicated(self):
  604         self.host.get_connection()
  605 
  606         # Test old version of libvirt. Should return single 'hypervisor'
  607         with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
  608             del mock_libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES
  609             caps = self.host.get_capabilities()
  610             cnt = [x.name for x in caps.host.cpu.features].count('xtpr')
  611             self.assertEqual(1, cnt)
  612 
  613         # Cleanup the capabilities cache firstly
  614         self.host._caps = None
  615 
  616         # Test new version of libvirt. Should still return single 'hypervisor'
  617         with mock.patch('nova.virt.libvirt.host.libvirt') as mock_libvirt:
  618             mock_libvirt['VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'] = 1
  619             caps = self.host.get_capabilities()
  620             cnt = [x.name for x in caps.host.cpu.features].count('xtpr')
  621             self.assertEqual(1, cnt)
  622 
  623     def test_baseline_cpu_not_supported(self):
  624         # Handle just the NO_SUPPORT error
  625         not_supported_exc = fakelibvirt.make_libvirtError(
  626                 fakelibvirt.libvirtError,
  627                 'this function is not supported by the connection driver:'
  628                 ' virConnectBaselineCPU',
  629                 error_code=fakelibvirt.VIR_ERR_NO_SUPPORT)
  630 
  631         with mock.patch.object(fakelibvirt.virConnect, 'baselineCPU',
  632                                side_effect=not_supported_exc):
  633             caps = self.host.get_capabilities()
  634             self.assertEqual(vconfig.LibvirtConfigCaps, type(caps))
  635             self.assertNotIn('aes', [x.name for x in caps.host.cpu.features])
  636 
  637         # Clear cached result so we can test again...
  638         self.host._caps = None
  639 
  640         # Other errors should not be caught
  641         other_exc = fakelibvirt.make_libvirtError(
  642             fakelibvirt.libvirtError,
  643             'other exc',
  644             error_code=fakelibvirt.VIR_ERR_NO_DOMAIN)
  645 
  646         with mock.patch.object(fakelibvirt.virConnect, 'baselineCPU',
  647                                side_effect=other_exc):
  648             self.assertRaises(fakelibvirt.libvirtError,
  649                               self.host.get_capabilities)
  650 
  651     def test_get_capabilities_no_host_cpu_model(self):
  652         """Tests that cpu features are not retrieved when the host cpu model
  653         is not in the capabilities.
  654         """
  655         fake_caps_xml = '''
  656 <capabilities>
  657   <host>
  658     <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
  659     <cpu>
  660       <arch>x86_64</arch>
  661       <vendor>Intel</vendor>
  662     </cpu>
  663   </host>
  664 </capabilities>'''
  665         with mock.patch.object(fakelibvirt.virConnect, 'getCapabilities',
  666                                return_value=fake_caps_xml):
  667             caps = self.host.get_capabilities()
  668             self.assertEqual(vconfig.LibvirtConfigCaps, type(caps))
  669             self.assertIsNone(caps.host.cpu.model)
  670             self.assertEqual(0, len(caps.host.cpu.features))
  671 
  672     def test__get_machine_types(self):
  673         expected = [
  674             # NOTE(aspiers): in the real world, i686 would probably
  675             # have q35 too, but our fixtures are manipulated to
  676             # exclude it to allow more thorough testing the our
  677             # canonical machine types logic is correct.
  678             ('i686', 'qemu', ['pc']),
  679             ('i686', 'kvm', ['pc']),
  680             ('x86_64', 'qemu', ['pc', 'q35']),
  681             ('x86_64', 'kvm', ['pc', 'q35']),
  682             ('armv7l', 'qemu', ['virt']),
  683             # NOTE(aspiers): we're currently missing default machine
  684             # types for the other architectures for which we have fake
  685             # capabilities.
  686         ]
  687         for arch, domain, expected_mach_types in expected:
  688             guest_xml = fake_libvirt_data.CAPABILITIES_GUEST[arch]
  689             guest = vconfig.LibvirtConfigCapsGuest()
  690             guest.parse_str(guest_xml)
  691             domain = guest.domains[domain]
  692             self.assertEqual(set(expected_mach_types),
  693                              self.host._get_machine_types(arch, domain),
  694                              "for arch %s domain %s" %
  695                              (arch, domain.domtype))
  696 
  697     def _test_get_domain_capabilities(self):
  698         caps = self.host.get_domain_capabilities()
  699         for arch, mtypes in caps.items():
  700             for mtype, dom_cap in mtypes.items():
  701                 self.assertIsInstance(dom_cap, vconfig.LibvirtConfigDomainCaps)
  702                 # NOTE(sean-k-mooney): this should always be true since we are
  703                 # mapping from an arch and machine_type to a domain cap object
  704                 # for that pair. We use 'in' to allow libvirt to expand the
  705                 # unversioned alias such as 'pc' or 'q35' to its versioned
  706                 # form e.g. pc-i440fx-2.11
  707                 self.assertIn(mtype, dom_cap.machine_type)
  708                 self.assertIn(dom_cap.machine_type_alias, mtype)
  709 
  710         # We assume we are testing with x86_64 in other parts of the code
  711         # so we just assert it's in the test data and return it.
  712         expected = [
  713             ('i686', ['pc', 'pc-i440fx-2.11']),
  714             ('x86_64', ['pc', 'pc-i440fx-2.11', 'q35', 'pc-q35-2.11']),
  715         ]
  716         for arch, expected_mtypes in expected:
  717             self.assertIn(arch, caps)
  718             for mach_type in expected_mtypes:
  719                 self.assertIn(mach_type, caps[arch], "for arch %s" % arch)
  720 
  721         return caps['x86_64']['pc']
  722 
  723     def test_get_domain_capabilities(self):
  724         caps = self._test_get_domain_capabilities()
  725         self.assertEqual(vconfig.LibvirtConfigDomainCaps, type(caps))
  726         # There is a <gic supported='no'/> feature in the fixture but
  727         # we don't parse that because nothing currently cares about it.
  728         self.assertEqual(0, len(caps.features))
  729 
  730     def test_get_domain_capabilities_non_native_kvm(self):
  731         # This test assumes that we are on a x86 host and the
  732         # virt-type is set to kvm. In that case we would expect
  733         # libvirt to raise an error if you try to get the domain
  734         # capabilities for non-native archs specifying the kvm virt
  735         # type.
  736         archs = {
  737             'sparc': 'SS-5',
  738             'mips': 'malta',
  739             'mipsel': 'malta',
  740             'ppc': 'g3beige',
  741             'armv7l': 'virt-2.11',
  742         }
  743 
  744         # Because we are mocking out the libvirt connection and
  745         # supplying fake data, no exception will be raised, so we
  746         # first store a reference to the original
  747         # _get_domain_capabilities function
  748         local__get_domain_caps = self.host._get_domain_capabilities
  749 
  750         # We then define our own version that will raise for
  751         # non-native archs and otherwise delegates to the private
  752         # function.
  753         def _get_domain_capabilities(**kwargs):
  754             arch = kwargs['arch']
  755             if arch not in archs:
  756                 return local__get_domain_caps(**kwargs)
  757             else:
  758                 exc = fakelibvirt.make_libvirtError(
  759                     fakelibvirt.libvirtError,
  760                     "invalid argument: KVM is not supported by "
  761                     "'/usr/bin/qemu-system-%s' on this host" % arch,
  762                     error_code=fakelibvirt.VIR_ERR_INVALID_ARG)
  763                 raise exc
  764 
  765         # Finally we patch to use our own version
  766         with test.nested(
  767             mock.patch.object(host.LOG, 'debug'),
  768             mock.patch.object(self.host, "_get_domain_capabilities"),
  769         ) as (mock_log, mock_caps):
  770             mock_caps.side_effect = _get_domain_capabilities
  771             self.flags(virt_type='kvm', group='libvirt')
  772             # and call self.host.get_domain_capabilities() directly as
  773             # the exception should be caught internally
  774             caps = self.host.get_domain_capabilities()
  775             # We don't really care what mock_caps is called with,
  776             # as we assert the behavior we expect below. However we
  777             # can at least check for the expected debug messages.
  778             mock_caps.assert_called()
  779             warnings = []
  780             for call in mock_log.mock_calls:
  781                 name, args, kwargs = call
  782                 if "Error from libvirt when retrieving domain capabilities" \
  783                         in args[0]:
  784                     warnings.append(call)
  785             self.assertTrue(len(warnings) > 0)
  786 
  787         # The resulting capabilities object should be non-empty
  788         # as the x86 archs won't raise a libvirtError exception
  789         self.assertTrue(len(caps) > 0)
  790         # but all of the archs we mocked out should be skipped and
  791         # not included in the result set
  792         for arch in archs:
  793             self.assertNotIn(arch, caps)
  794 
  795     def test_get_domain_capabilities_other_archs(self):
  796         # NOTE(aspiers): only architectures which are returned by
  797         # fakelibvirt's getCapabilities() can be tested here, since
  798         # Host.get_domain_capabilities() iterates over those
  799         # architectures.
  800         archs = {
  801             'sparc': 'SS-5',
  802             'mips': 'malta',
  803             'mipsel': 'malta',
  804             'ppc': 'g3beige',
  805             'armv7l': 'virt-2.11',
  806         }
  807 
  808         caps = self.host.get_domain_capabilities()
  809 
  810         for arch, mtype in archs.items():
  811             self.assertIn(arch, caps)
  812             self.assertNotIn('pc', caps[arch])
  813             self.assertIn(mtype, caps[arch])
  814             self.assertEqual(mtype, caps[arch][mtype].machine_type)
  815 
  816     def test_get_domain_capabilities_with_versioned_machine_type(self):
  817         caps = self.host.get_domain_capabilities()
  818 
  819         # i686 supports both an unversioned pc alias and
  820         # a versioned form.
  821         i686 = caps['i686']
  822         self.assertIn('pc', i686)
  823         self.assertIn('pc-i440fx-2.11', i686)
  824         # both the versioned and unversioned forms
  825         # have the unversioned name available as a machine_type_alias
  826         unversioned_caps = i686['pc']
  827         self.assertEqual('pc', unversioned_caps.machine_type_alias)
  828         versioned_caps = i686['pc-i440fx-2.11']
  829         self.assertEqual('pc', versioned_caps.machine_type_alias)
  830         # the unversioned_caps and versioned_caps
  831         # are equal and are actually the same object.
  832         self.assertEqual(unversioned_caps, versioned_caps)
  833         self.assertIs(unversioned_caps, versioned_caps)
  834 
  835     @mock.patch.object(fakelibvirt.virConnect, '_domain_capability_features',
  836                        new='')
  837     def test_get_domain_capabilities_no_features(self):
  838         caps = self._test_get_domain_capabilities()
  839         self.assertEqual(vconfig.LibvirtConfigDomainCaps, type(caps))
  840         features = caps.features
  841         self.assertEqual([], features)
  842 
  843     def _test_get_domain_capabilities_sev(self, supported):
  844         caps = self._test_get_domain_capabilities()
  845         self.assertEqual(vconfig.LibvirtConfigDomainCaps, type(caps))
  846         features = caps.features
  847         self.assertEqual(1, len(features))
  848         sev = features[0]
  849         self.assertEqual(vconfig.LibvirtConfigDomainCapsFeatureSev, type(sev))
  850         self.assertEqual(supported, sev.supported)
  851         if supported:
  852             self.assertEqual(47, sev.cbitpos)
  853             self.assertEqual(1, sev.reduced_phys_bits)
  854 
  855     @mock.patch.object(
  856         fakelibvirt.virConnect, '_domain_capability_features', new=
  857         fakelibvirt.virConnect._domain_capability_features_with_SEV_unsupported
  858     )
  859     def test_get_domain_capabilities_sev_unsupported(self):
  860         self._test_get_domain_capabilities_sev(False)
  861 
  862     @mock.patch.object(
  863         fakelibvirt.virConnect, '_domain_capability_features',
  864         new=fakelibvirt.virConnect._domain_capability_features_with_SEV)
  865     def test_get_domain_capabilities_sev_supported(self):
  866         self._test_get_domain_capabilities_sev(True)
  867 
  868     @mock.patch.object(fakelibvirt.virConnect, "getHostname")
  869     def test_get_hostname_caching(self, mock_hostname):
  870         mock_hostname.return_value = "foo"
  871         self.assertEqual('foo', self.host.get_hostname())
  872         mock_hostname.assert_called_with()
  873 
  874         mock_hostname.reset_mock()
  875 
  876         mock_hostname.return_value = "bar"
  877         self.assertEqual('foo', self.host.get_hostname())
  878         mock_hostname.assert_called_with()
  879 
  880     @mock.patch.object(fakelibvirt.virConnect, "getType")
  881     def test_get_driver_type(self, mock_type):
  882         mock_type.return_value = "qemu"
  883         self.assertEqual("qemu", self.host.get_driver_type())
  884         mock_type.assert_called_once_with()
  885 
  886     @mock.patch.object(fakelibvirt.virConnect, "getVersion")
  887     def test_get_version(self, mock_version):
  888         mock_version.return_value = 1005001
  889         self.assertEqual(1005001, self.host.get_version())
  890         mock_version.assert_called_once_with()
  891 
  892     @mock.patch.object(fakelibvirt.virConnect, "secretLookupByUsage")
  893     def test_find_secret(self, mock_sec):
  894         """finding secrets with various usage_type."""
  895         expected = [
  896             mock.call(fakelibvirt.VIR_SECRET_USAGE_TYPE_CEPH, 'rbdvol'),
  897             mock.call(fakelibvirt.VIR_SECRET_USAGE_TYPE_CEPH, 'cephvol'),
  898             mock.call(fakelibvirt.VIR_SECRET_USAGE_TYPE_ISCSI, 'iscsivol'),
  899             mock.call(fakelibvirt.VIR_SECRET_USAGE_TYPE_VOLUME, 'vol')]
  900 
  901         self.host.find_secret('rbd', 'rbdvol')
  902         self.host.find_secret('ceph', 'cephvol')
  903         self.host.find_secret('iscsi', 'iscsivol')
  904         self.host.find_secret('volume', 'vol')
  905         self.assertEqual(expected, mock_sec.mock_calls)
  906         self.assertRaises(exception.NovaException,
  907                           self.host.find_secret, "foo", "foovol")
  908 
  909         mock_sec.side_effect = fakelibvirt.libvirtError("")
  910         mock_sec.side_effect.err = (66, )
  911         self.assertIsNone(self.host.find_secret('rbd', 'rbdvol'))
  912 
  913     @mock.patch.object(fakelibvirt.virConnect, "secretDefineXML")
  914     def test_create_secret(self, mock_sec):
  915         """creating secrets with various usage_type."""
  916         self.host.create_secret('rbd', 'rbdvol')
  917         self.host.create_secret('ceph', 'cephvol')
  918         self.host.create_secret('iscsi', 'iscsivol')
  919         self.host.create_secret('volume', 'vol')
  920         self.host.create_secret('vtpm', 'vtpmdev')
  921         self.assertRaises(exception.NovaException,
  922                           self.host.create_secret, "foo", "foovol")
  923 
  924         secret = mock.MagicMock()
  925         mock_sec.return_value = secret
  926         self.host.create_secret('iscsi', 'iscsivol', password="foo")
  927         secret.setValue.assert_called_once_with("foo")
  928 
  929     @mock.patch('nova.virt.libvirt.host.Host.find_secret')
  930     def test_delete_secret(self, mock_find_secret):
  931         """deleting secret."""
  932         secret = mock.MagicMock()
  933         mock_find_secret.return_value = secret
  934         expected = [mock.call('rbd', 'rbdvol'),
  935                     mock.call().undefine()]
  936         self.host.delete_secret('rbd', 'rbdvol')
  937         self.assertEqual(expected, mock_find_secret.mock_calls)
  938 
  939         mock_find_secret.return_value = None
  940         self.host.delete_secret("rbd", "rbdvol")
  941 
  942     def test_get_memory_total(self):
  943         with mock.patch.object(host.Host, "get_connection") as mock_conn:
  944             mock_conn().getInfo.return_value = ['zero', 'one', 'two']
  945             self.assertEqual('one', self.host.get_memory_mb_total())
  946 
  947     def test_get_memory_total_file_backed(self):
  948         self.flags(file_backed_memory=1048576, group="libvirt")
  949         self.assertEqual(1048576, self.host.get_memory_mb_total())
  950 
  951     def test_get_memory_used(self):
  952         m = mock.mock_open(read_data="""
  953 MemTotal:       16194180 kB
  954 MemFree:          233092 kB
  955 MemAvailable:    8892356 kB
  956 Buffers:          567708 kB
  957 Cached:          8362404 kB
  958 SwapCached:            0 kB
  959 Active:          8381604 kB
  960 """)
  961         with test.nested(
  962             mock.patch.object(builtins, "open", m, create=True),
  963             mock.patch.object(host.Host, "get_connection"),
  964         ) as (mock_file, mock_conn):
  965             mock_conn().getInfo.return_value = [
  966                 obj_fields.Architecture.X86_64, 15814, 8, 1208, 1, 1, 4, 2]
  967 
  968             self.assertEqual(6866, self.host.get_memory_mb_used())
  969 
  970     def test_sum_domain_memory_mb_xen(self):
  971         class DiagFakeDomain(object):
  972             def __init__(self, id, memmb):
  973                 self.id = id
  974                 self.memmb = memmb
  975 
  976             def info(self):
  977                 return [0, 0, self.memmb * 1024]
  978 
  979             def ID(self):
  980                 return self.id
  981 
  982             def name(self):
  983                 return "instance000001"
  984 
  985             def UUIDString(self):
  986                 return uuids.fake
  987 
  988         m = mock.mock_open(read_data="""
  989 MemTotal:       16194180 kB
  990 MemFree:          233092 kB
  991 MemAvailable:    8892356 kB
  992 Buffers:          567708 kB
  993 Cached:          8362404 kB
  994 SwapCached:            0 kB
  995 Active:          8381604 kB
  996 """)
  997 
  998         with test.nested(
  999                 mock.patch.object(six.moves.builtins, "open", m, create=True),
 1000                 mock.patch.object(host.Host,
 1001                                   "list_guests"),
 1002                 mock.patch.object(libvirt_driver.LibvirtDriver,
 1003                                   "_conn"),
 1004         ) as (mock_file, mock_list, mock_conn):
 1005             mock_list.return_value = [
 1006                 libvirt_guest.Guest(DiagFakeDomain(0, 15814)),
 1007                 libvirt_guest.Guest(DiagFakeDomain(1, 750)),
 1008                 libvirt_guest.Guest(DiagFakeDomain(2, 1042))]
 1009             mock_conn.getInfo.return_value = [
 1010                 obj_fields.Architecture.X86_64, 15814, 8, 1208, 1, 1, 4, 2]
 1011 
 1012             self.assertEqual(8657, self.host._sum_domain_memory_mb())
 1013             mock_list.assert_called_with(only_guests=False)
 1014 
 1015     def test_get_memory_used_xen(self):
 1016         self.flags(virt_type='xen', group='libvirt')
 1017         with mock.patch.object(
 1018             self.host, "_sum_domain_memory_mb"
 1019         ) as mock_sumDomainMemory:
 1020             mock_sumDomainMemory.return_value = 8192
 1021             self.assertEqual(8192, self.host.get_memory_mb_used())
 1022             mock_sumDomainMemory.assert_called_once_with(include_host=True)
 1023 
 1024     def test_sum_domain_memory_mb_file_backed(self):
 1025         class DiagFakeDomain(object):
 1026             def __init__(self, id, memmb):
 1027                 self.id = id
 1028                 self.memmb = memmb
 1029 
 1030             def info(self):
 1031                 return [0, 0, self.memmb * 1024]
 1032 
 1033             def ID(self):
 1034                 return self.id
 1035 
 1036             def name(self):
 1037                 return "instance000001"
 1038 
 1039             def UUIDString(self):
 1040                 return uuids.fake
 1041 
 1042         with mock.patch.object(host.Host, 'list_guests') as mock_list:
 1043             mock_list.return_value = [
 1044                 libvirt_guest.Guest(DiagFakeDomain(0, 4096)),
 1045                 libvirt_guest.Guest(DiagFakeDomain(1, 2048)),
 1046                 libvirt_guest.Guest(DiagFakeDomain(2, 1024)),
 1047                 libvirt_guest.Guest(DiagFakeDomain(3, 1024))]
 1048 
 1049             self.assertEqual(8192,
 1050                     self.host._sum_domain_memory_mb(include_host=False))
 1051 
 1052     def test_get_memory_used_file_backed(self):
 1053         self.flags(file_backed_memory=1048576,
 1054                    group='libvirt')
 1055 
 1056         with mock.patch.object(
 1057             self.host, "_sum_domain_memory_mb"
 1058         ) as mock_sumDomainMemory:
 1059             mock_sumDomainMemory.return_value = 8192
 1060             self.assertEqual(8192, self.host.get_memory_mb_used())
 1061             mock_sumDomainMemory.assert_called_once_with(include_host=False)
 1062 
 1063     def test_get_cpu_stats(self):
 1064         stats = self.host.get_cpu_stats()
 1065         self.assertEqual(
 1066             {'kernel': 5664160000000,
 1067              'idle': 1592705190000000,
 1068              'frequency': 800,
 1069              'user': 26728850000000,
 1070              'iowait': 6121490000000},
 1071             stats)
 1072 
 1073     @mock.patch.object(fakelibvirt.virConnect, "defineXML")
 1074     def test_write_instance_config(self, mock_defineXML):
 1075         fake_dom_xml = """
 1076                 <domain type='kvm'>
 1077                   <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
 1078                   <devices>
 1079                     <disk type='file'>
 1080                       <source file='filename'/>
 1081                     </disk>
 1082                   </devices>
 1083                 </domain>
 1084             """
 1085         conn = self.host.get_connection()
 1086         dom = fakelibvirt.Domain(conn,
 1087                                  fake_dom_xml,
 1088                                  False)
 1089         mock_defineXML.return_value = dom
 1090         guest = self.host.write_instance_config(fake_dom_xml)
 1091         mock_defineXML.assert_called_once_with(fake_dom_xml)
 1092         self.assertIsInstance(guest, libvirt_guest.Guest)
 1093 
 1094     def test_write_instance_config_unicode(self):
 1095         fake_dom_xml = u"""
 1096                 <domain type='kvm'>
 1097                   <uuid>cef19ce0-0ca2-11df-855d-b19fbce37686</uuid>
 1098                   <devices>
 1099                     <disk type='file'>
 1100                       <source file='\u4e2d\u6587'/>
 1101                     </disk>
 1102                   </devices>
 1103                 </domain>
 1104             """
 1105 
 1106         def emulate_defineXML(xml):
 1107             conn = self.host.get_connection()
 1108             dom = fakelibvirt.Domain(conn, xml, False)
 1109             return dom
 1110         with mock.patch.object(fakelibvirt.virConnect, "defineXML"
 1111                                ) as mock_defineXML:
 1112             mock_defineXML.side_effect = emulate_defineXML
 1113             guest = self.host.write_instance_config(fake_dom_xml)
 1114             self.assertIsInstance(guest, libvirt_guest.Guest)
 1115 
 1116     @mock.patch.object(fakelibvirt.virConnect, "nodeDeviceLookupByName")
 1117     def test_device_lookup_by_name(self, mock_nodeDeviceLookupByName):
 1118         self.host.device_lookup_by_name("foo")
 1119         mock_nodeDeviceLookupByName.assert_called_once_with("foo")
 1120 
 1121     def test_list_pci_devices(self):
 1122         with mock.patch.object(self.host, "_list_devices") as mock_listDevices:
 1123             self.host.list_pci_devices(8)
 1124         mock_listDevices.assert_called_once_with('pci', flags=8)
 1125 
 1126     def test_list_mdev_capable_devices(self):
 1127         with mock.patch.object(self.host, "_list_devices") as mock_listDevices:
 1128             self.host.list_mdev_capable_devices(8)
 1129         mock_listDevices.assert_called_once_with('mdev_types', flags=8)
 1130 
 1131     def test_list_mediated_devices(self):
 1132         with mock.patch.object(self.host, "_list_devices") as mock_listDevices:
 1133             self.host.list_mediated_devices(8)
 1134         mock_listDevices.assert_called_once_with('mdev', flags=8)
 1135 
 1136     def test_list_all_devices(self):
 1137         with mock.patch.object(
 1138                 self.host.get_connection(),
 1139                 "listAllDevices") as mock_list_all_devices:
 1140             xml_str = """
 1141         <device>
 1142         <name>pci_0000_04_00_3</name>
 1143         <parent>pci_0000_00_01_1</parent>
 1144         <driver>
 1145             <name>igb</name>
 1146         </driver>
 1147         <capability type='pci'>
 1148             <domain>0</domain>
 1149             <bus>4</bus>
 1150             <slot>0</slot>
 1151             <function>3</function>
 1152             <product id='0x1521'>I350 Gigabit Network Connection</product>
 1153             <vendor id='0x8086'>Intel Corporation</vendor>
 1154             <capability type='virt_functions'>
 1155               <address domain='0x0000' bus='0x04' slot='0x10' function='0x3'/>
 1156               <address domain='0x0000' bus='0x04' slot='0x10' function='0x7'/>
 1157               <address domain='0x0000' bus='0x04' slot='0x11' function='0x3'/>
 1158               <address domain='0x0000' bus='0x04' slot='0x11' function='0x7'/>
 1159             </capability>
 1160         </capability>
 1161       </device>"""
 1162             pci_dev = fakelibvirt.NodeDevice(None, xml=xml_str)
 1163             node_devs = [pci_dev]
 1164             mock_list_all_devices.return_value = node_devs
 1165             ret = self.host.list_all_devices(flags=42)
 1166             self.assertEqual(node_devs, ret)
 1167         mock_list_all_devices.assert_called_once_with(42)
 1168 
 1169     def test_list_all_devices_raises(self):
 1170         with mock.patch.object(
 1171                 self.host.get_connection(),
 1172                 "listAllDevices") as mock_list_all_devices:
 1173             xml_str = """
 1174         <device>
 1175         <name>pci_0000_04_00_3</name>
 1176         <parent>pci_0000_00_01_1</parent>
 1177         <driver>
 1178             <name>igb</name>
 1179         </driver>
 1180         <capability type='pci'>
 1181             <domain>0</domain>
 1182             <bus>4</bus>
 1183             <slot>0</slot>
 1184             <function>3</function>
 1185             <product id='0x1521'>I350 Gigabit Network Connection</product>
 1186             <vendor id='0x8086'>Intel Corporation</vendor>
 1187             <capability type='virt_functions'>
 1188               <address domain='0x0000' bus='0x04' slot='0x10' function='0x3'/>
 1189               <address domain='0x0000' bus='0x04' slot='0x10' function='0x7'/>
 1190               <address domain='0x0000' bus='0x04' slot='0x11' function='0x3'/>
 1191               <address domain='0x0000' bus='0x04' slot='0x11' function='0x7'/>
 1192             </capability>
 1193         </capability>
 1194       </device>"""
 1195             pci_dev = fakelibvirt.NodeDevice(None, xml=xml_str)
 1196             node_devs = [pci_dev]
 1197             mock_list_all_devices.return_value = node_devs
 1198             mock_list_all_devices.side_effect = fakelibvirt.libvirtError(
 1199                 "message")
 1200             ret = self.host.list_all_devices(flags=42)
 1201             self.assertEqual([], ret)
 1202         mock_list_all_devices.assert_called_once_with(42)
 1203 
 1204     @mock.patch.object(fakelibvirt.virConnect, "listDevices")
 1205     def test_list_devices(self, mock_listDevices):
 1206         self.host._list_devices('mdev', 8)
 1207         mock_listDevices.assert_called_once_with('mdev', 8)
 1208 
 1209     @mock.patch.object(fakelibvirt.virConnect, "listDevices")
 1210     def test_list_devices_unsupported(self, mock_listDevices):
 1211         not_supported_exc = fakelibvirt.make_libvirtError(
 1212                 fakelibvirt.libvirtError,
 1213                 'this function is not supported by the connection driver:'
 1214                 ' listDevices',
 1215                 error_code=fakelibvirt.VIR_ERR_NO_SUPPORT)
 1216         mock_listDevices.side_effect = not_supported_exc
 1217         self.assertEqual([], self.host._list_devices('mdev', 8))
 1218 
 1219     @mock.patch.object(fakelibvirt.virConnect, "listDevices")
 1220     def test_list_devices_other_exc(self, mock_listDevices):
 1221         mock_listDevices.side_effect = fakelibvirt.libvirtError('test')
 1222         self.assertRaises(fakelibvirt.libvirtError,
 1223                           self.host._list_devices, 'mdev', 8)
 1224 
 1225     @mock.patch.object(fakelibvirt.virConnect, "compareCPU")
 1226     def test_compare_cpu(self, mock_compareCPU):
 1227         self.host.compare_cpu("cpuxml")
 1228         mock_compareCPU.assert_called_once_with("cpuxml", 0)
 1229 
 1230     def test_is_cpu_control_policy_capable_ok(self):
 1231         m = mock.mock_open(
 1232             read_data="""cg /cgroup/cpu,cpuacct cg opt1,cpu,opt3 0 0
 1233 cg /cgroup/memory cg opt1,opt2 0 0
 1234 """)
 1235         with mock.patch(
 1236                 "six.moves.builtins.open", m, create=True):
 1237             self.assertTrue(self.host.is_cpu_control_policy_capable())
 1238 
 1239     def test_is_cpu_control_policy_capable_ko(self):
 1240         m = mock.mock_open(
 1241             read_data="""cg /cgroup/cpu,cpuacct cg opt1,opt2,opt3 0 0
 1242 cg /cgroup/memory cg opt1,opt2 0 0
 1243 """)
 1244         with mock.patch(
 1245                 "six.moves.builtins.open", m, create=True):
 1246             self.assertFalse(self.host.is_cpu_control_policy_capable())
 1247 
 1248     @mock.patch('six.moves.builtins.open', side_effect=IOError)
 1249     def test_is_cpu_control_policy_capable_ioerror(self, mock_open):
 1250         self.assertFalse(self.host.is_cpu_control_policy_capable())
 1251 
 1252     @mock.patch('nova.virt.libvirt.host.libvirt.Connection.getCapabilities')
 1253     def test_has_hyperthreading__true(self, mock_cap):
 1254         mock_cap.return_value = """
 1255         <capabilities>
 1256           <host>
 1257             <uuid>1f71d34a-7c89-45cf-95ce-3df20fc6b936</uuid>
 1258             <cpu>
 1259             </cpu>
 1260             <topology>
 1261               <cells num='1'>
 1262                 <cell id='0'>
 1263                   <cpus num='4'>
 1264                     <cpu id='0' socket_id='0' core_id='0' siblings='0,2'/>
 1265                     <cpu id='1' socket_id='0' core_id='1' siblings='1,3'/>
 1266                     <cpu id='2' socket_id='0' core_id='0' siblings='0,2'/>
 1267                     <cpu id='3' socket_id='0' core_id='1' siblings='1,3'/>
 1268                   </cpus>
 1269                 </cell>
 1270               </cells>
 1271             </topology>
 1272           </host>
 1273         </capabilities>
 1274         """
 1275         self.assertTrue(self.host.has_hyperthreading)
 1276 
 1277     @mock.patch('nova.virt.libvirt.host.libvirt.Connection.getCapabilities')
 1278     def test_has_hyperthreading__false(self, mock_cap):
 1279         mock_cap.return_value = """
 1280         <capabilities>
 1281           <host>
 1282             <uuid>1f71d34a-7c89-45cf-95ce-3df20fc6b936</uuid>
 1283             <cpu>
 1284             </cpu>
 1285             <topology>
 1286               <cells num='1'>
 1287                 <cell id='0'>
 1288                   <cpus num='4'>
 1289                     <cpu id='0' socket_id='0' core_id='0' siblings='0'/>
 1290                     <cpu id='1' socket_id='0' core_id='1' siblings='1'/>
 1291                     <cpu id='2' socket_id='0' core_id='2' siblings='2'/>
 1292                     <cpu id='3' socket_id='0' core_id='3' siblings='3'/>
 1293                   </cpus>
 1294                 </cell>
 1295               </cells>
 1296             </topology>
 1297           </host>
 1298         </capabilities>
 1299         """
 1300         self.assertFalse(self.host.has_hyperthreading)
 1301 
 1302 
 1303 vc = fakelibvirt.virConnect
 1304 
 1305 
 1306 class TestLibvirtSEV(test.NoDBTestCase):
 1307     """Libvirt host tests for AMD SEV support."""
 1308 
 1309     def setUp(self):
 1310         super(TestLibvirtSEV, self).setUp()
 1311 
 1312         self.useFixture(fakelibvirt.FakeLibvirtFixture())
 1313         self.host = host.Host("qemu:///system")
 1314 
 1315 
 1316 class TestLibvirtSEVUnsupported(TestLibvirtSEV):
 1317     @mock.patch.object(os.path, 'exists', return_value=False)
 1318     def test_kernel_parameter_missing(self, fake_exists):
 1319         self.assertFalse(self.host._kernel_supports_amd_sev())
 1320         fake_exists.assert_called_once_with(
 1321             '/sys/module/kvm_amd/parameters/sev')
 1322 
 1323     @mock.patch.object(os.path, 'exists', return_value=True)
 1324     @mock.patch.object(builtins, 'open', mock.mock_open(read_data="0\n"))
 1325     def test_kernel_parameter_zero(self, fake_exists):
 1326         self.assertFalse(self.host._kernel_supports_amd_sev())
 1327         fake_exists.assert_called_once_with(
 1328             '/sys/module/kvm_amd/parameters/sev')
 1329 
 1330     @mock.patch.object(os.path, 'exists', return_value=True)
 1331     @mock.patch.object(builtins, 'open', mock.mock_open(read_data="1\n"))
 1332     def test_kernel_parameter_one(self, fake_exists):
 1333         self.assertTrue(self.host._kernel_supports_amd_sev())
 1334         fake_exists.assert_called_once_with(
 1335             '/sys/module/kvm_amd/parameters/sev')
 1336 
 1337     @mock.patch.object(os.path, 'exists', return_value=True)
 1338     @mock.patch.object(builtins, 'open', mock.mock_open(read_data="1\n"))
 1339     def test_unsupported_without_feature(self, fake_exists):
 1340         self.assertFalse(self.host.supports_amd_sev)
 1341 
 1342     @mock.patch.object(os.path, 'exists', return_value=True)
 1343     @mock.patch.object(builtins, 'open', mock.mock_open(read_data="1\n"))
 1344     @mock.patch.object(vc, '_domain_capability_features',
 1345         new=vc._domain_capability_features_with_SEV_unsupported)
 1346     def test_unsupported_with_feature(self, fake_exists):
 1347         self.assertFalse(self.host.supports_amd_sev)
 1348 
 1349 
 1350 class TestLibvirtSEVSupported(TestLibvirtSEV):
 1351     """Libvirt driver tests for when AMD SEV support is present."""
 1352 
 1353     @mock.patch.object(os.path, 'exists', return_value=True)
 1354     @mock.patch.object(builtins, 'open', mock.mock_open(read_data="1\n"))
 1355     @mock.patch.object(vc, '_domain_capability_features',
 1356                        new=vc._domain_capability_features_with_SEV)
 1357     def test_supported_with_feature(self, fake_exists):
 1358         self.assertTrue(self.host.supports_amd_sev)
 1359 
 1360 
 1361 class LibvirtTpoolProxyTestCase(test.NoDBTestCase):
 1362     def setUp(self):
 1363         super(LibvirtTpoolProxyTestCase, self).setUp()
 1364 
 1365         self.useFixture(fakelibvirt.FakeLibvirtFixture())
 1366         self.host = host.Host("qemu:///system")
 1367 
 1368         def _stub_xml(uuid):
 1369             return ("<domain>"
 1370                     "  <uuid>" + uuid + "</uuid>"
 1371                     "  <name>" + uuid + "</name>"
 1372                     "</domain>")
 1373 
 1374         self.conn = self.host.get_connection()
 1375         self.conn.defineXML(_stub_xml(uuids.vm1)).create()
 1376         self.conn.defineXML(_stub_xml(uuids.vm2)).create()
 1377 
 1378     def test_get_libvirt_proxy_classes(self):
 1379         proxy_classes = host.Host._get_libvirt_proxy_classes(host.libvirt)
 1380 
 1381         # Assert the classes we're using currently
 1382         # NOTE(mdbooth): We're obviously asserting the wrong classes here
 1383         # because we're explicitly asserting the faked versions. This is a
 1384         # concession to avoid a test dependency on libvirt.
 1385         self.assertIn(fakelibvirt.virDomain, proxy_classes)
 1386         self.assertIn(fakelibvirt.virConnect, proxy_classes)
 1387         self.assertIn(fakelibvirt.virNodeDevice, proxy_classes)
 1388         self.assertIn(fakelibvirt.virSecret, proxy_classes)
 1389 
 1390         # Assert that we filtered out libvirtError and any private classes
 1391         self.assertNotIn(fakelibvirt.libvirtError, proxy_classes)
 1392         self.assertNotIn(fakelibvirt._EventAddHandleFunc, proxy_classes)
 1393 
 1394     def test_tpool_get_connection(self):
 1395         # Test that Host.get_connection() returns a tpool.Proxy
 1396         self.assertIsInstance(self.conn, tpool.Proxy)
 1397 
 1398     def test_tpool_instance_lookup(self):
 1399         # Test that domains returns by our libvirt connection are also proxied
 1400         dom = self.conn.lookupByUUIDString(uuids.vm1)
 1401         self.assertIsInstance(dom, tpool.Proxy)
 1402 
 1403     def test_tpool_list_all_connections(self):
 1404         # Test that Host.list_all_connections() returns a list of proxied
 1405         # virDomain objects
 1406 
 1407         domains = self.host.list_instance_domains()
 1408         self.assertEqual(2, len(domains))
 1409         for domain in domains:
 1410             self.assertIsInstance(domain, tpool.Proxy)
 1411             self.assertIn(domain.UUIDString(), (uuids.vm1, uuids.vm2))