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