summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJohannes Erdfelt <johannes.erdfelt@rackspace.com>2011-06-15 22:28:32 +0000
committerJohannes Erdfelt <johannes.erdfelt@rackspace.com>2011-06-15 22:28:32 +0000
commit7620db9454dd391ce3080e99cdb8237eaa9a4835 (patch)
treefa71b98126bd37412b29f38e17980b3fc6cc287c /nova
parent357556ce52af91cc4273597c6576bd9da8e5b388 (diff)
Windows instances will often take a few minutes setting up the image on first
boot and then reboot. We should be more patient for those systems as well check if the domid changes so we can send agent requests to the current domid
Diffstat (limited to 'nova')
-rw-r--r--nova/virt/xenapi/vmops.py60
1 files changed, 49 insertions, 11 deletions
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 6b61ca9b5..190bf7c20 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -25,6 +25,7 @@ import M2Crypto
import os
import pickle
import subprocess
+import time
import uuid
from nova import context
@@ -44,7 +45,10 @@ from nova.virt.xenapi.vm_utils import ImageType
XenAPI = None
LOG = logging.getLogger("nova.virt.xenapi.vmops")
+
FLAGS = flags.FLAGS
+flags.DEFINE_integer('windows_version_timeout', 300,
+ 'time to wait for windows agent to be fully operational')
def _cmp_version(a, b):
@@ -244,7 +248,16 @@ class VMOps(object):
'architecture': instance.architecture})
def _check_agent_version():
- version = self.get_agent_version(instance)
+ if instance.os_type == 'windows':
+ # Windows will generally perform a setup process on first boot
+ # that can take a couple of minutes and then reboot. So we
+ # need to be more patient than normal as well as watch for
+ # domid changes
+ version = self.get_agent_version(instance,
+ timeout=FLAGS.windows_version_timeout,
+ check_domid_changes=True)
+ else:
+ version = self.get_agent_version(instance)
if not version:
LOG.info(_('No agent version returned by instance'))
return
@@ -500,18 +513,43 @@ class VMOps(object):
task = self._session.call_xenapi('Async.VM.clean_reboot', vm_ref)
self._session.wait_for_task(task, instance.id)
- def get_agent_version(self, instance):
+ def get_agent_version(self, instance, timeout=None,
+ check_domid_changes=False):
"""Get the version of the agent running on the VM instance."""
- # Send the encrypted password
- transaction_id = str(uuid.uuid4())
- args = {'id': transaction_id}
- resp = self._make_agent_call('version', instance, '', args)
- if resp is None:
- # No response from the agent
- return
- resp_dict = json.loads(resp)
- return resp_dict['message']
+ def _call():
+ # Send the encrypted password
+ transaction_id = str(uuid.uuid4())
+ args = {'id': transaction_id}
+ resp = self._make_agent_call('version', instance, '', args)
+ if resp is None:
+ # No response from the agent
+ return
+ resp_dict = json.loads(resp)
+ return resp_dict['message']
+
+ if timeout:
+ vm_ref = self._get_vm_opaque_ref(instance)
+ vm_rec = self._session.get_xenapi().VM.get_record(vm_ref)
+
+ domid = vm_rec['domid']
+
+ timeout = time.time() + timeout
+ while time.time() < timeout:
+ ret = _call()
+ if ret:
+ return ret
+
+ if check_domid_changes:
+ vm_rec = self._session.get_xenapi().VM.get_record(vm_ref)
+ if vm_rec['domid'] != domid:
+ LOG.info(_('domid changed from %(olddomid)s to '
+ '%(newdomid)s') % {
+ 'olddomid': domid,
+ 'newdomid': vm_rec['domid']})
+ domid = vm_rec['domid']
+ else:
+ return _call()
def agent_update(self, instance, url, md5sum):
"""Update agent on the VM instance."""