+ pidfile, pid, alive = self._InstancePidAlive(instance.name)
+ if not alive:
+ raise errors.HypervisorError("Failed to reboot instance %s: not running" %
+ (instance.name))
+ # StopInstance will delete the saved KVM runtime so:
+ # ...first load it...
+ kvm_runtime = self._LoadKVMRuntime(instance)
+ # ...now we can safely call StopInstance...
+ if not self.StopInstance(instance):
+ self.StopInstance(instance, force=True)
+ # ...and finally we can save it again, and execute it...
+ self._SaveKVMRuntime(instance, kvm_runtime)
+ self._ExecuteKVMRuntime(instance, kvm_runtime)
+
+ def MigrationInfo(self, instance):
+ """Get instance information to perform a migration.
+
+ @type instance: L{objects.Instance}
+ @param instance: instance to be migrated
+ @rtype: string
+ @return: content of the KVM runtime file
+
+ """
+ return self._ReadKVMRuntime(instance.name)
+
+ def AcceptInstance(self, instance, info, target):
+ """Prepare to accept an instance.
+
+ @type instance: L{objects.Instance}
+ @param instance: instance to be accepted
+ @type info: string
+ @param info: content of the KVM runtime file on the source node
+ @type target: string
+ @param target: target host (usually ip), on this node
+
+ """
+ kvm_runtime = self._LoadKVMRuntime(instance, serialized_runtime=info)
+ incoming_address = (target, constants.KVM_MIGRATION_PORT)
+ self._ExecuteKVMRuntime(instance, kvm_runtime, incoming=incoming_address)
+
+ def FinalizeMigration(self, instance, info, success):
+ """Finalize an instance migration.
+
+ Stop the incoming mode KVM.
+
+ @type instance: L{objects.Instance}
+ @param instance: instance whose migration is being aborted
+
+ """
+ if success:
+ self._WriteKVMRuntime(instance.name, info)
+ else:
+ self.StopInstance(instance, force=True)
+
+ def MigrateInstance(self, instance_name, target, live):
+ """Migrate an instance to a target node.
+
+ The migration will not be attempted if the instance is not
+ currently running.
+
+ @type instance_name: string
+ @param instance_name: name of the instance to be migrated
+ @type target: string
+ @param target: ip address of the target node
+ @type live: boolean
+ @param live: perform a live migration
+
+ """
+ pidfile, pid, alive = self._InstancePidAlive(instance_name)
+ if not alive:
+ raise errors.HypervisorError("Instance not running, cannot migrate")
+
+ if not live:
+ self._CallMonitorCommand(instance_name, 'stop')
+
+ migrate_command = ('migrate -d tcp:%s:%s' %
+ (target, constants.KVM_MIGRATION_PORT))
+ self._CallMonitorCommand(instance_name, migrate_command)
+
+ info_command = 'info migrate'
+ done = False
+ while not done:
+ result = self._CallMonitorCommand(instance_name, info_command)
+ match = self._MIGRATION_STATUS_RE.search(result.stdout)
+ if not match:
+ raise errors.HypervisorError("Unknown 'info migrate' result: %s" %
+ result.stdout)
+ else:
+ status = match.group(1)
+ if status == 'completed':
+ done = True
+ elif status == 'active':
+ time.sleep(2)
+ elif status == 'failed' or status == 'cancelled':
+ if not live:
+ self._CallMonitorCommand(instance_name, 'cont')
+ raise errors.HypervisorError("Migration %s at the kvm level" %
+ status)
+ else:
+ logging.info("KVM: unknown migration status '%s'" % status)
+ time.sleep(2)
+
+ utils.KillProcess(pid)
+ utils.RemoveFile(pidfile)
+ utils.RemoveFile(self._InstanceMonitor(instance_name))
+ utils.RemoveFile(self._InstanceSerial(instance_name))
+ utils.RemoveFile(self._InstanceKVMRuntime(instance_name))