Avoid multiple initializations of Host class

nova.virt.libvirt.host.Host class manages nova interaction with
libvirtd. During processing of HUP signal, object of this class
could be initialized multiple times. This leads to resource leak
(pipes and threads) and the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/eventlet/hubs/poll.py",
line 115, in wait
    listener.cb(fileno)
  File "/usr/local/lib/python2.7/dist-packages/eventlet/greenthread.py",
line 214, in main
    result = function(*args, **kwargs)
  File "/opt/stack/nova/nova/utils.py", line 1053, in context_wrapper
    return func(*args, **kwargs)
  File "/opt/stack/nova/nova/virt/libvirt/host.py", line 131, in
_dispatch_thread
    self._dispatch_events()
  File "/opt/stack/nova/nova/virt/libvirt/host.py", line 236, in
_dispatch_events

This commit avoids multiple initializations of the same Host object.
Thus it fixes the above problems.

Change-Id: I9cfdbca4986ee6da1e8c42bc0b4477d7d0cb5041
Closes-bug: #1599688
Signed-off-by: Xuanzhou Perry Dong <oss_xzdong@163.com>
This commit is contained in:
Xuanzhou Perry Dong 2016-07-08 12:01:31 +08:00
parent 1870c75c45
commit 3a1ca56487
2 changed files with 11 additions and 0 deletions

View File

@ -63,6 +63,12 @@ class HostTestCase(test.NoDBTestCase):
self.useFixture(fakelibvirt.FakeLibvirtFixture())
self.host = host.Host("qemu:///system")
@mock.patch("nova.virt.libvirt.host.Host._init_events")
def test_repeat_initialization(self, mock_init_events):
for i in range(3):
self.host.initialize()
mock_init_events.assert_called_once_with()
@mock.patch.object(fakelibvirt.virConnect, "registerCloseCallback")
def test_close_callback(self, mock_close):
self.close_callback = None

View File

@ -105,6 +105,8 @@ class Host(object):
# STOPPED lifecycle event some seconds.
self._lifecycle_delay = 15
self._initialized = False
def _native_thread(self):
"""Receives async events coming in from libvirtd.
@ -469,6 +471,9 @@ class Host(object):
pass
def initialize(self):
if self._initialized:
return
# NOTE(dkliban): Error handler needs to be registered before libvirt
# connection is used for the first time. Otherwise, the
# handler does not get registered.