Permalink
Browse files

Virt: turn timeout values into definitions

This tries to replace values on timeouts (sometimes repeated over
multiple places) with definitions of them. The approach is to use
those definitions as default values, but still allowing a function
caller to pass a specific timeout.

This way, if a specific timeout need tweaking, it's much simpler
to do so. This tweaking can also be necessary only on a specific
monitor or VM implementation, so we keep them separate.

aexpect.py has not received the same treatment because it is
a library that has broad and general use.

Signed-off-by: Cleber Rosa <crosa@redhat.com>
  • Loading branch information...
1 parent 216eff1 commit b638c9c3a5f9fdee07281b1e232832c94d300458 @clebergnu clebergnu committed Nov 23, 2011
Showing with 87 additions and 46 deletions.
  1. +2 −4 client/virt/aexpect.py
  2. +32 −20 client/virt/kvm_monitor.py
  3. +23 −9 client/virt/kvm_vm.py
  4. +4 −2 client/virt/libvirt_monitor.py
  5. +26 −11 client/virt/virt_vm.py
View
@@ -898,15 +898,13 @@ def __getinitargs__(self):
return Tail.__getinitargs__(self)
- def read_nonblocking(self, timeout=None):
+ def read_nonblocking(self, timeout=0.1):
"""
Read from child until there is nothing to read for timeout seconds.
@param timeout: Time (seconds) to wait before we give up reading from
- the child process, or None to use the default value.
+ the child process.
"""
- if timeout is None:
- timeout = 0.1
fd = self._get_fd("expect")
data = ""
while True:
View
@@ -60,6 +60,9 @@ class Monitor:
Common code for monitor classes.
"""
+ ACQUIRE_LOCK_TIMEOUT = 20
+ DATA_AVAILABLE_TIMEOUT = 0
+
def __init__(self, name, filename):
"""
Initialize the instance.
@@ -110,7 +113,8 @@ def _close_sock(self):
pass
self._socket.close()
- def _acquire_lock(self, timeout=20):
+
+ def _acquire_lock(self, timeout=ACQUIRE_LOCK_TIMEOUT):
end_time = time.time() + timeout
while time.time() < end_time:
if self._lock.acquire(False):
@@ -119,7 +123,7 @@ def _acquire_lock(self, timeout=20):
return False
- def _data_available(self, timeout=0):
+ def _data_available(self, timeout=DATA_AVAILABLE_TIMEOUT):
timeout = max(0, timeout)
try:
return bool(select.select([self._socket], [], [], timeout)[0])
@@ -157,6 +161,9 @@ class HumanMonitor(Monitor):
Wraps "human monitor" commands.
"""
+ PROMPT_TIMEOUT = 20
+ CMD_TIMEOUT = 20
+
def __init__(self, name, filename, suppress_exceptions=False):
"""
Connect to the monitor socket and find the (qemu) prompt.
@@ -176,7 +183,7 @@ def __init__(self, name, filename, suppress_exceptions=False):
self.protocol = "human"
# Find the initial (qemu) prompt
- s, o = self._read_up_to_qemu_prompt(20)
+ s, o = self._read_up_to_qemu_prompt()
if not s:
raise MonitorProtocolError("Could not find (qemu) prompt "
"after connecting to monitor. "
@@ -195,7 +202,7 @@ def __init__(self, name, filename, suppress_exceptions=False):
# Private methods
- def _read_up_to_qemu_prompt(self, timeout=20):
+ def _read_up_to_qemu_prompt(self, timeout=PROMPT_TIMEOUT):
s = ""
end_time = time.time() + timeout
while self._data_available(end_time - time.time()):
@@ -219,7 +226,7 @@ def _send(self, cmd):
@raise MonitorLockError: Raised if the lock cannot be acquired
@raise MonitorSocketError: Raised if a socket error occurs
"""
- if not self._acquire_lock(20):
+ if not self._acquire_lock():
raise MonitorLockError("Could not acquire exclusive lock to send "
"monitor command '%s'" % cmd)
@@ -236,7 +243,7 @@ def _send(self, cmd):
# Public methods
- def cmd(self, command, timeout=20, debug=True, fd=None):
+ def cmd(self, command, timeout=CMD_TIMEOUT, debug=True, fd=None):
"""
Send command to the monitor.
@@ -252,7 +259,7 @@ def cmd(self, command, timeout=20, debug=True, fd=None):
if debug:
logging.debug("(monitor %s) Sending command '%s'",
self.name, command)
- if not self._acquire_lock(20):
+ if not self._acquire_lock():
raise MonitorLockError("Could not acquire exclusive lock to send "
"monitor command '%s'" % command)
@@ -313,7 +320,7 @@ def verify_status(self, status):
# cmd().
# - A command wrapper should use self._help_str if it requires information
# about the monitor's capabilities.
- def send_args_cmd(self, cmdlines, timeout=20, convert=True):
+ def send_args_cmd(self, cmdlines, timeout=CMD_TIMEOUT, convert=True):
"""
Send a command with/without parameters and return its output.
Have same effect with cmd function.
@@ -463,6 +470,11 @@ class QMPMonitor(Monitor):
Wraps QMP monitor commands.
"""
+ READ_OBJECTS_TIMEOUT = 5
+ CMD_TIMEOUT = 20
+ RESPONSE_TIMEOUT = 20
+ PROMPT_TIMEOUT = 20
+
def __init__(self, name, filename, suppress_exceptions=False):
"""
Connect to the monitor socket, read the greeting message and issue the
@@ -528,7 +540,7 @@ def _build_cmd(self, cmd, args=None, id=None):
return obj
- def _read_objects(self, timeout=5):
+ def _read_objects(self, timeout=READ_OBJECTS_TIMEOUT):
"""
Read lines from the monitor and try to decode them.
Stop when all available lines have been successfully decoded, or when
@@ -580,7 +592,7 @@ def _send(self, data):
raise MonitorSocketError("Could not send data: %r" % data, e)
- def _get_response(self, id=None, timeout=20):
+ def _get_response(self, id=None, timeout=RESPONSE_TIMEOUT):
"""
Read a response from the QMP monitor.
@@ -600,7 +612,7 @@ def _get_response(self, id=None, timeout=20):
# Public methods
- def cmd(self, cmd, args=None, timeout=20, debug=True):
+ def cmd(self, cmd, args=None, timeout=CMD_TIMEOUT, debug=True):
"""
Send a QMP monitor command and return the response.
@@ -621,7 +633,7 @@ def cmd(self, cmd, args=None, timeout=20, debug=True):
if debug:
logging.debug("(monitor %s) Sending command '%s'",
self.name, cmd)
- if not self._acquire_lock(20):
+ if not self._acquire_lock():
raise MonitorLockError("Could not acquire exclusive lock to send "
"QMP command '%s'" % cmd)
@@ -653,7 +665,7 @@ def cmd(self, cmd, args=None, timeout=20, debug=True):
self._lock.release()
- def cmd_raw(self, data, timeout=20):
+ def cmd_raw(self, data, timeout=CMD_TIMEOUT):
"""
Send a raw string to the QMP monitor and return the response.
Unlike cmd(), return the raw response dict without performing any
@@ -666,7 +678,7 @@ def cmd_raw(self, data, timeout=20):
@raise MonitorSocketError: Raised if a socket error occurs
@raise MonitorProtocolError: Raised if no response is received
"""
- if not self._acquire_lock(20):
+ if not self._acquire_lock():
raise MonitorLockError("Could not acquire exclusive lock to send "
"data: %r" % data)
@@ -683,7 +695,7 @@ def cmd_raw(self, data, timeout=20):
self._lock.release()
- def cmd_obj(self, obj, timeout=20):
+ def cmd_obj(self, obj, timeout=CMD_TIMEOUT):
"""
Transform a Python object to JSON, send the resulting string to the QMP
monitor, and return the response.
@@ -697,10 +709,10 @@ def cmd_obj(self, obj, timeout=20):
@raise MonitorSocketError: Raised if a socket error occurs
@raise MonitorProtocolError: Raised if no response is received
"""
- return self.cmd_raw(json.dumps(obj) + "\n")
+ return self.cmd_raw(json.dumps(obj) + "\n", timeout)
- def cmd_qmp(self, cmd, args=None, id=None, timeout=20):
+ def cmd_qmp(self, cmd, args=None, id=None, timeout=CMD_TIMEOUT):
"""
Build a QMP command from the passed arguments, send it to the monitor
and return the response.
@@ -751,7 +763,7 @@ def get_events(self):
@return: A list of events (the objects returned have an "event" key)
@raise MonitorLockError: Raised if the lock cannot be acquired
"""
- if not self._acquire_lock(20):
+ if not self._acquire_lock():
raise MonitorLockError("Could not acquire exclusive lock to read "
"QMP events")
try:
@@ -779,7 +791,7 @@ def clear_events(self):
@raise MonitorLockError: Raised if the lock cannot be acquired
"""
- if not self._acquire_lock(20):
+ if not self._acquire_lock():
raise MonitorLockError("Could not acquire exclusive lock to clear "
"QMP event list")
self._events = []
@@ -796,7 +808,7 @@ def get_greeting(self):
# Command wrappers
# Note: all of the following functions raise exceptions in a similar manner
# to cmd().
- def send_args_cmd(self, cmdlines, timeout=20, convert=True):
+ def send_args_cmd(self, cmdlines, timeout=CMD_TIMEOUT, convert=True):
"""
Send a command with/without parameters and return its output.
Have same effect with cmd function.
View
@@ -17,6 +17,17 @@ class VM(virt_vm.BaseVM):
MIGRATION_PROTOS = ['tcp', 'unix', 'exec']
+ #
+ # By default we inherit all timeouts from the base VM class
+ #
+ LOGIN_TIMEOUT = virt_vm.BaseVM.LOGIN_TIMEOUT
+ LOGIN_WAIT_TIMEOUT = virt_vm.BaseVM.LOGIN_WAIT_TIMEOUT
+ COPY_FILES_TIMEOUT = virt_vm.BaseVM.COPY_FILES_TIMEOUT
+ MIGRATE_TIMEOUT = virt_vm.BaseVM.MIGRATE_TIMEOUT
+ REBOOT_TIMEOUT = virt_vm.BaseVM.REBOOT_TIMEOUT
+ CREATE_TIMEOUT = virt_vm.BaseVM.CREATE_TIMEOUT
+ CLOSE_SESSION_TIMEOUT = 30
+
def __init__(self, name, params, root_dir, address_cache, state=None):
"""
Initialize the object and set a few attributes.
@@ -635,8 +646,8 @@ def add_usb(help, usb_id, usb_type, multifunction=False,
@error.context_aware
- def create(self, name=None, params=None, root_dir=None, timeout=5.0,
- migration_mode=None, mac_source=None):
+ def create(self, name=None, params=None, root_dir=None,
+ timeout=CREATE_TIMEOUT, migration_mode=None, mac_source=None):
"""
Start the VM by running a qemu command.
All parameters are optional. If name, params or root_dir are not
@@ -1301,9 +1312,10 @@ def del_nic(self, nic_info, wait=20):
@error.context_aware
- def migrate(self, timeout=3600, protocol="tcp", cancel_delay=None,
- offline=False, stable_check=False, clean=True,
- save_path="/tmp", dest_host="localhost", remote_port=None):
+ def migrate(self, timeout=MIGRATE_TIMEOUT, protocol="tcp",
+ cancel_delay=None, offline=False, stable_check=False,
+ clean=True, save_path="/tmp", dest_host="localhost",
+ remote_port=None):
"""
Migrate the VM.
@@ -1457,7 +1469,8 @@ def wait_for_migration():
@error.context_aware
- def reboot(self, session=None, method="shell", nic_index=0, timeout=240):
+ def reboot(self, session=None, method="shell", nic_index=0,
+ timeout=REBOOT_TIMEOUT):
"""
Reboot the VM and wait for it to come back up by trying to log in until
timeout expires.
@@ -1497,9 +1510,10 @@ def reboot(self, session=None, method="shell", nic_index=0, timeout=240):
raise virt_vm.VMRebootError("Unknown reboot method: %s" % method)
error.context("waiting for guest to go down", logging.info)
- if not virt_utils.wait_for(lambda:
- not session.is_responsive(timeout=30),
- 120, 0, 1):
+ if not virt_utils.wait_for(
+ lambda:
+ not session.is_responsive(timeout=self.CLOSE_SESSION_TIMEOUT),
+ timeout / 2, 0, 1):
raise virt_vm.VMRebootError("Guest refuses to go down")
session.close()
@@ -8,6 +8,8 @@ class VirshMonitor:
Wraps "Virsh monitor" commands.
"""
+ LOGIN_TIMEOUT = 10
+
def __init__(self, virsh_exec, name, vmname, password=None,
prompt=None, hostname='localhost', driver=None, username=None,
linesep="\\n"):
@@ -61,7 +63,7 @@ def __getinitargs__(self):
self.hostname, self.driver, self.username)
- def login(self, timeout=10):
+ def login(self, timeout=LOGIN_TIMEOUT):
"""
Log into the hypervisor using required URIs .
@@ -83,7 +85,7 @@ def login(self, timeout=10):
if self.username is not None:
try:
virt_utils._remote_login(session, self.username, self.password,
- self.prompt, self.timeout)
+ self.prompt, timeout)
except aexpect.ShellError:
session.close()
session = None
Oops, something went wrong.

0 comments on commit b638c9c

Please sign in to comment.