diff options
| -rw-r--r-- | nova/tests/test_xenapi.py | 5 | ||||
| -rw-r--r-- | nova/virt/xenapi/vmops.py | 137 |
2 files changed, 66 insertions, 76 deletions
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index f0bc8c85f..eecbc82b8 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -188,7 +188,7 @@ class XenAPIVolumeTestCase(test.TestCase): self.stubs.UnsetAll() -def reset_network(*args): +def configure_instance(*args): pass @@ -214,7 +214,8 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_get_this_vm_uuid(self.stubs) stubs.stubout_stream_disk(self.stubs) stubs.stubout_is_vdi_pv(self.stubs) - self.stubs.Set(vmops.VMOps, 'reset_network', reset_network) + self.stubs.Set(vmops.VMOps, '_configure_instance', + configure_instance) self.stubs.Set(vmops.VMOps, '_find_rescue_vbd_ref', _find_rescue_vbd_ref) stubs.stub_out_vm_methods(self.stubs) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 01d06ab04..764f7e800 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -29,6 +29,7 @@ import sys import time import uuid +from eventlet import greenthread import M2Crypto from nova.compute import api as compute @@ -55,6 +56,9 @@ FLAGS = flags.FLAGS flags.DEFINE_integer('agent_version_timeout', 300, 'number of seconds to wait for agent to be fully ' 'operational') +flags.DEFINE_integer('xenapi_running_timeout', 60, + 'number of seconds to wait for instance to go to ' + 'running state') flags.DEFINE_string('xenapi_vif_driver', 'nova.virt.xenapi.vif.XenAPIBridgeDriver', 'The XenAPI VIF driver using XenServer Network APIs.') @@ -383,6 +387,42 @@ class VMOps(object): bootable=False) userdevice += 1 + def _configure_instance(self, ctx, instance, vm_ref): + # Inject files, if necessary + injected_files = instance.injected_files + if injected_files: + # Check if this is a JSON-encoded string and convert if needed. + if isinstance(injected_files, basestring): + try: + injected_files = json.loads(injected_files) + except ValueError: + LOG.exception( + _("Invalid value for injected_files: '%s'") + % injected_files) + injected_files = [] + # Inject any files, if specified + for path, contents in instance.injected_files: + LOG.debug(_("Injecting file path: '%s'") % path) + self.inject_file(instance, path, contents) + + # Set admin password, if necessary + admin_password = instance.admin_pass + if admin_password: + LOG.debug(_("Setting admin password")) + self.set_admin_password(instance, admin_password) + + # Reset network config + LOG.debug(_("Resetting network")) + self.reset_network(instance, vm_ref) + + # Set VCPU weight + inst_type = db.instance_type_get(ctx, instance.instance_type_id) + vcpu_weight = inst_type["vcpu_weight"] + if str(vcpu_weight) != "None": + LOG.debug(_("Setting VCPU weight")) + self._session.call_xenapi("VM.add_to_VCPUs_params", vm_ref, + "weight", vcpu_weight) + def _spawn(self, instance, vm_ref): """Spawn a new instance.""" LOG.debug(_('Starting VM %s...'), vm_ref) @@ -404,83 +444,32 @@ class VMOps(object): 'os': instance.os_type, 'architecture': instance.architecture}) - def _check_agent_version(): - LOG.debug(_("Querying agent version")) + # Wait for boot to finish + LOG.debug(_('Instance %s: waiting for running'), instance_name) + expiration = time.time() + FLAGS.xenapi_running_timeout + while time.time() < expiration: + state = self.get_info(instance_name)['state'] + if state == power_state.RUNNING: + break + + greenthread.sleep(0.5) - version = self.get_agent_version(instance) - if not version: - return + LOG.debug(_('Instance %s: running'), instance_name) + # Update agent, if necessary + # This also waits until the agent starts + LOG.debug(_("Querying agent version")) + version = self.get_agent_version(instance) + if version: LOG.info(_('Instance agent version: %s') % version) - if not agent_build: - return - - if cmp_version(version, agent_build['version']) < 0: - LOG.info(_('Updating Agent to %s') % agent_build['version']) - self.agent_update(instance, agent_build['url'], - agent_build['md5hash']) - - def _inject_files(): - injected_files = instance.injected_files - if injected_files: - # Check if this is a JSON-encoded string and convert if needed. - if isinstance(injected_files, basestring): - try: - injected_files = json.loads(injected_files) - except ValueError: - LOG.exception( - _("Invalid value for injected_files: '%s'") - % injected_files) - injected_files = [] - # Inject any files, if specified - for path, contents in instance.injected_files: - LOG.debug(_("Injecting file path: '%s'") % path) - self.inject_file(instance, path, contents) - - def _set_admin_password(): - admin_password = instance.admin_pass - if admin_password: - LOG.debug(_("Setting admin password")) - self.set_admin_password(instance, admin_password) - - def _reset_network(): - LOG.debug(_("Resetting network")) - self.reset_network(instance, vm_ref) - - def _set_vcpu_weight(): - inst_type = db.instance_type_get(ctx, instance.instance_type_id) - vcpu_weight = inst_type["vcpu_weight"] - if str(vcpu_weight) != "None": - LOG.debug(_("Setting VCPU weight")) - self._session.call_xenapi("VM.add_to_VCPUs_params", vm_ref, - "weight", vcpu_weight) - - # NOTE(armando): Do we really need to do this in virt? - # NOTE(tr3buchet): not sure but wherever we do it, we need to call - # reset_network afterwards - timer = utils.LoopingCall(f=None) - - def _wait_for_boot(): - try: - state = self.get_info(instance_name)['state'] - if state == power_state.RUNNING: - LOG.debug(_('Instance %s: booted'), instance_name) - timer.stop() - _check_agent_version() - _inject_files() - _set_admin_password() - _reset_network() - _set_vcpu_weight() - return True - except Exception, exc: - LOG.warn(exc) - LOG.exception(_('Instance %s: failed to boot'), instance_name) - timer.stop() - return False - - timer.f = _wait_for_boot - - return timer.start(interval=0.5, now=True) + + if version and agent_build and \ + cmp_version(version, agent_build['version']) < 0: + LOG.info(_('Updating Agent to %s') % agent_build['version']) + self.agent_update(instance, agent_build['url'], + agent_build['md5hash']) + + self._configure_instance(ctx, instance, vm_ref) def _handle_spawn_error(self, vdis, spawn_error): # Extract resource list from spawn_error. |
