Change in vdsm[master]: agent: Guest agent reply capability support
vfeenstr at redhat.com
vfeenstr at redhat.com
Mon Feb 15 12:35:31 UTC 2016
Vinzenz Feenstra has uploaded a new change for review.
Change subject: agent: Guest agent reply capability support
......................................................................
agent: Guest agent reply capability support
This patch adds the ability to wait for a reply of the guest agent
to certain messsages. This is required for instance required for the
lifecycle events to allow the guest to complete some operation before
vdsm continues.
Change-Id: I00f2f26ec34728c9ad3599734bca90aa407f3c98
Signed-off-by: Vinzenz Feenstra <vfeenstr at redhat.com>
---
M vdsm/virt/guestagent.py
1 file changed, 41 insertions(+), 5 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/24/53524/1
diff --git a/vdsm/virt/guestagent.py b/vdsm/virt/guestagent.py
index bac3dd7..d970c5f 100644
--- a/vdsm/virt/guestagent.py
+++ b/vdsm/virt/guestagent.py
@@ -18,12 +18,15 @@
# Refer to the README and COPYING files for full details of the license
#
+import contextlib
import logging
import time
import socket
import errno
import json
import re
+import threading
+import uuid
from vdsm import supervdsm
from vdsm import utils
@@ -33,6 +36,7 @@
_MAX_SUPPORTED_API_VERSION = 3
_IMPLICIT_API_VERSION_ZERO = 0
+_REPLY_CAP_MIN_VERSION = 3
_MESSAGE_API_VERSION_LOOKUP = {
'set-number-of-cpus': 1,
@@ -117,8 +121,10 @@
def __init__(self, agent):
self._agent = agent
- def before_hibernation(self):
- self._agent.send_lifecycle_event('before_hibernation')
+ def before_hibernation(self, wait_timeout=None):
+ id = uuid.uuid4()
+ with self._agent._waitable_message(wait_timeout, id):
+ self._agent.send_lifecycle_event('before_hibernation', reply_id=id)
def after_hibernation_failure(self):
self._agent.send_lifecycle_event('after_hibernation', failure=True)
@@ -126,10 +132,12 @@
def after_hibernation(self):
self._agent.send_lifecycle_event('after_hibernation')
- def before_migration(self):
- self._agent.send_lifecycle_event('before_migration')
+ def before_migration(self, wait_timeout=None):
+ id = uuid.uuid4()
+ with self._agent._waitable_message(wait_timeout, id):
+ self._agent.send_lifecycle_event('before_migration', reply_id=id)
- def after_migration_failure(self, reason):
+ def after_migration_failure(self):
self._agent.send_lifecycle_event('after_migration', failure=True)
def after_migration(self):
@@ -164,6 +172,32 @@
self._channelListener = channelListener
self._messageState = MessageState.NORMAL
self.events = GuestAgentEvents(self)
+ self._completion_lock = threading.Lock()
+ self._completion_handlers = {}
+
+ def _on_completion(self, id, args):
+ with self._completion_lock:
+ handler = self._completion_handler.pop(id, None)
+ if handler and callable(handler):
+ handler(id, args)
+
+ @property
+ def can_reply(self):
+ active = self.isResponsive()
+ return active and self.effectiveApiVersion >= _REPLY_CAP_MIN_VERSION
+
+ @contextlib.contextmanager
+ def _waitable_message(self, wait_timeout, id):
+ if self.can_reply and wait_timeout is not None:
+ event = threading.Event()
+ with self._completion_lock:
+ self._completion_handlers[id] = lambda _, __: event.set()
+ yield
+ event.wait(wait_timeout)
+ with self._completion_lock:
+ self._completion_handlers.pop(id, None)
+ else:
+ yield
@property
def guestStatus(self):
@@ -361,6 +395,8 @@
self.guestDiskMapping = args.get('mapping', {})
elif message == 'number-of-cpus':
self.guestInfo['guestCPUCount'] = int(args['count'])
+ elif message == 'completion':
+ self._on_completion(args.pop('reply_id', None), args)
else:
self.log.error('Unknown message type %s', message)
--
To view, visit https://gerrit.ovirt.org/53524
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I00f2f26ec34728c9ad3599734bca90aa407f3c98
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Vinzenz Feenstra <vfeenstr at redhat.com>
More information about the vdsm-patches
mailing list