X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/dab69e9770b1c733dbbf8effb34beda317a4f3d8..a162cf5b6e67d48b048df0cd03bdaeb8e5bbdb70:/lib/backend.py diff --git a/lib/backend.py b/lib/backend.py index c0b5467..d4d1030 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -260,8 +260,9 @@ def AddNode(dsa, dsapub, rsa, rsapub, sshkey, sshpub): priv_key, pub_key, auth_keys = ssh.GetUserFiles(constants.GANETI_RUNAS, mkdir=True) except errors.OpExecError, err: - logging.exception("Error while processing user ssh files") - return False + msg = "Error while processing user ssh files" + logging.exception(msg) + return (False, "%s: %s" % (msg, err)) for name, content in [(priv_key, sshkey), (pub_key, sshpub)]: utils.WriteFile(name, data=content, mode=0600) @@ -270,7 +271,7 @@ def AddNode(dsa, dsapub, rsa, rsapub, sshkey, sshpub): utils.RunCmd([constants.SSH_INITD_SCRIPT, "restart"]) - return True + return (True, "Node added successfully") def LeaveCluster(): @@ -426,12 +427,21 @@ def VerifyNode(what, cluster_name): result[constants.NV_VGLIST] = ListVolumeGroups() if constants.NV_VERSION in what: - result[constants.NV_VERSION] = constants.PROTOCOL_VERSION + result[constants.NV_VERSION] = (constants.PROTOCOL_VERSION, + constants.RELEASE_VERSION) if constants.NV_HVINFO in what: hyper = hypervisor.GetHypervisor(what[constants.NV_HVINFO]) result[constants.NV_HVINFO] = hyper.GetNodeInfo() + if constants.NV_DRBDLIST in what: + try: + used_minors = bdev.DRBD8.GetUsedDevs().keys() + except errors.BlockDeviceError: + logging.warning("Can't get used minors list", exc_info=True) + used_minors = [] + result[constants.NV_DRBDLIST] = used_minors + return result @@ -681,9 +691,12 @@ def AddOSToInstance(instance): logging.error("os create command '%s' returned error: %s, logfile: %s," " output: %s", result.cmd, result.fail_reason, logfile, result.output) - return False + lines = [val.encode("string_escape") + for val in utils.TailFile(logfile, lines=20)] + return (False, "OS create script failed (%s), last lines in the" + " log file:\n%s" % (result.fail_reason, "\n".join(lines))) - return True + return (True, "Successfully installed") def RunRenameInstance(instance, old_name): @@ -712,9 +725,12 @@ def RunRenameInstance(instance, old_name): if result.failed: logging.error("os create command '%s' returned error: %s output: %s", result.cmd, result.fail_reason, result.output) - return False + lines = [val.encode("string_escape") + for val in utils.TailFile(logfile, lines=20)] + return (False, "OS rename script failed (%s), last lines in the" + " log file:\n%s" % (result.fail_reason, "\n".join(lines))) - return True + return (True, "Rename successful") def _GetVGInfo(vg_name): @@ -845,7 +861,7 @@ def StartInstance(instance, extra_args): running_instances = GetInstanceList([instance.hypervisor]) if instance.name in running_instances: - return True + return (True, "Already running") try: block_devices = _GatherAndLinkBlockDevs(instance) @@ -853,13 +869,13 @@ def StartInstance(instance, extra_args): hyper.StartInstance(instance, block_devices, extra_args) except errors.BlockDeviceError, err: logging.exception("Failed to start instance") - return False + return (False, "Block device error: %s" % str(err)) except errors.HypervisorError, err: logging.exception("Failed to start instance") _RemoveBlockDevLinks(instance.name, instance.disks) - return False + return (False, "Hypervisor error: %s" % str(err)) - return True + return (True, "Instance started successfully") def ShutdownInstance(instance): @@ -883,7 +899,7 @@ def ShutdownInstance(instance): try: hyper.StopInstance(instance) except errors.HypervisorError, err: - logging.error("Failed to stop instance") + logging.error("Failed to stop instance: %s" % err) return False # test every 10secs for 2min @@ -895,17 +911,18 @@ def ShutdownInstance(instance): time.sleep(10) else: # the shutdown did not succeed - logging.error("shutdown of '%s' unsuccessful, using destroy", instance) + logging.error("Shutdown of '%s' unsuccessful, using destroy", + instance.name) try: hyper.StopInstance(instance, force=True) except errors.HypervisorError, err: - logging.exception("Failed to stop instance") + logging.exception("Failed to stop instance: %s" % err) return False time.sleep(1) if instance.name in GetInstanceList([hv_name]): - logging.error("could not shutdown instance '%s' even by destroy", + logging.error("Could not shutdown instance '%s' even by destroy", instance.name) return False @@ -959,6 +976,65 @@ def RebootInstance(instance, reboot_type, extra_args): return True +def MigrationInfo(instance): + """Gather information about an instance to be migrated. + + @type instance: L{objects.Instance} + @param instance: the instance definition + + """ + hyper = hypervisor.GetHypervisor(instance.hypervisor) + try: + info = hyper.MigrationInfo(instance) + except errors.HypervisorError, err: + msg = "Failed to fetch migration information" + logging.exception(msg) + return (False, '%s: %s' % (msg, err)) + return (True, info) + + +def AcceptInstance(instance, info, target): + """Prepare the node to accept an instance. + + @type instance: L{objects.Instance} + @param instance: the instance definition + @type info: string/data (opaque) + @param info: migration information, from the source node + @type target: string + @param target: target host (usually ip), on this node + + """ + hyper = hypervisor.GetHypervisor(instance.hypervisor) + try: + hyper.AcceptInstance(instance, info, target) + except errors.HypervisorError, err: + msg = "Failed to accept instance" + logging.exception(msg) + return (False, '%s: %s' % (msg, err)) + return (True, "Accept successfull") + + +def FinalizeMigration(instance, info, success): + """Finalize any preparation to accept an instance. + + @type instance: L{objects.Instance} + @param instance: the instance definition + @type info: string/data (opaque) + @param info: migration information, from the source node + @type success: boolean + @param success: whether the migration was a success or a failure + + """ + hyper = hypervisor.GetHypervisor(instance.hypervisor) + try: + hyper.FinalizeMigration(instance, info, success) + except errors.HypervisorError, err: + msg = "Failed to finalize migration" + logging.exception(msg) + return (False, '%s: %s' % (msg, err)) + return (True, "Migration Finalized") + + def MigrateInstance(instance, target, live): """Migrates an instance to another node. @@ -1518,6 +1594,7 @@ def OSEnvironment(instance, debug=0): result = {} result['OS_API_VERSION'] = '%d' % constants.OS_API_VERSION result['INSTANCE_NAME'] = instance.name + result['INSTANCE_OS'] = instance.os result['HYPERVISOR'] = instance.hypervisor result['DISK_COUNT'] = '%d' % len(instance.disks) result['NIC_COUNT'] = '%d' % len(instance.nics) @@ -1530,7 +1607,7 @@ def OSEnvironment(instance, debug=0): real_disk.Open() result['DISK_%d_PATH' % idx] = real_disk.dev_path # FIXME: When disks will have read-only mode, populate this - result['DISK_%d_ACCESS' % idx] = 'W' + result['DISK_%d_ACCESS' % idx] = disk.mode if constants.HV_DISK_TYPE in instance.hvparams: result['DISK_%d_FRONTEND_TYPE' % idx] = \ instance.hvparams[constants.HV_DISK_TYPE]