summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYun Mao <yunmao@gmail.com>2012-03-13 16:15:19 -0400
committerYun Mao <yunmao@gmail.com>2012-03-14 16:49:23 -0400
commitcaf25ef8d3bdb49a6f23ee9789342558c53b9172 (patch)
tree2cdefe0850a23efbd9549b62d633ea114b5d1a4e
parentf40357574245d2e3b8cb7995cb27adc8e9b99175 (diff)
nonblocking libvirt mode using tpool
Add an option libvirt_nonblocking (disabled by default) to use a thread pool to execute all libvirt API calls. Previously all the calls except one in firewall.py are blocking in the eventlet thread model. Change-Id: I665ed7a629bb029011b181e8d2844fc2276502d9
-rw-r--r--etc/nova/nova.conf.sample2
-rw-r--r--nova/virt/libvirt/connection.py15
-rw-r--r--nova/virt/libvirt/firewall.py8
3 files changed, 23 insertions, 2 deletions
diff --git a/etc/nova/nova.conf.sample b/etc/nova/nova.conf.sample
index 1ff6ec357..afdedfbd3 100644
--- a/etc/nova/nova.conf.sample
+++ b/etc/nova/nova.conf.sample
@@ -740,6 +740,8 @@
# libvirt_disk_prefix=<None>
###### (BoolOpt) Inject the admin password at boot time, without an agent.
# libvirt_inject_password=false
+###### (BoolOpt) Use a separated OS thread pool to realize non-blocking libvirt calls. Disabled by default.
+# libvirt_nonblocking=false
###### (StrOpt) Libvirt domain type (valid options are: kvm, lxc, qemu, uml, xen)
# libvirt_type="kvm"
###### (StrOpt) Override the default libvirt URI (which is dependent on libvirt_type)
diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
index 5603b1e26..58154c4a4 100644
--- a/nova/virt/libvirt/connection.py
+++ b/nova/virt/libvirt/connection.py
@@ -50,6 +50,8 @@ import time
import uuid
from eventlet import greenthread
+from eventlet import tpool
+
from xml.dom import minidom
from xml.etree import ElementTree
@@ -154,6 +156,10 @@ libvirt_opts = [
help='Number of seconds to wait for instance to shut down after'
' soft reboot request is made. We fall back to hard reboot'
' if instance does not shutdown within this window.'),
+ cfg.BoolOpt('libvirt_nonblocking',
+ default=False,
+ help='Use a separated OS thread pool to realize non-blocking'
+ ' libvirt calls')
]
FLAGS = flags.FLAGS
@@ -249,9 +255,16 @@ class LibvirtConnection(driver.ComputeDriver):
def _get_connection(self):
if not self._wrapped_conn or not self._test_connection():
LOG.debug(_('Connecting to libvirt: %s'), self.uri)
- self._wrapped_conn = self._connect(self.uri,
+ if not FLAGS.libvirt_nonblocking:
+ self._wrapped_conn = self._connect(self.uri,
self.read_only)
+ else:
+ self._wrapped_conn = tpool.proxy_call(
+ (libvirt.virDomain, libvirt.virConnect),
+ self._connect, self.uri, self.read_only)
+
return self._wrapped_conn
+
_conn = property(_get_connection)
def _test_connection(self):
diff --git a/nova/virt/libvirt/firewall.py b/nova/virt/libvirt/firewall.py
index 04b3cf42a..dd491ea5f 100644
--- a/nova/virt/libvirt/firewall.py
+++ b/nova/virt/libvirt/firewall.py
@@ -144,7 +144,13 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
if callable(xml):
xml = xml()
# execute in a native thread and block current greenthread until done
- tpool.execute(self._conn.nwfilterDefineXML, xml)
+ if not FLAGS.libvirt_nonblocking:
+ # NOTE(maoy): the original implementation is to have the API called
+ # in the thread pool no matter what.
+ tpool.execute(self._conn.nwfilterDefineXML, xml)
+ else:
+ # NOTE(maoy): self._conn is a eventlet.tpool.Proxy object
+ self._conn.nwfilterDefineXML(xml)
def unfilter_instance(self, instance, network_info):
"""Clear out the nwfilter rules."""