X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/e557bae9fb6e3d23172c3a638f8973477a9283d9..9205a895ac0b5d60b881458a44bb157b88eac21d:/lib/backend.py diff --git a/lib/backend.py b/lib/backend.py index 183286b..ae07ae1 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -1326,15 +1326,16 @@ def BlockdevAddchildren(parent_cdev, new_cdevs): """ parent_bdev = _RecursiveFindBD(parent_cdev) if parent_bdev is None: - logging.error("Can't find parent device") - return False + msg = "Can't find parent device '%s' in add children" % str(parent_cdev) + logging.error("BlockdevAddchildren: %s", msg) + return (False, msg) new_bdevs = [_RecursiveFindBD(disk) for disk in new_cdevs] if new_bdevs.count(None) > 0: - logging.error("Can't find new device(s) to add: %s:%s", - new_bdevs, new_cdevs) - return False + msg = "Can't find new device(s) to add: %s:%s" % (new_bdevs, new_cdevs) + logging.error(msg) + return (False, msg) parent_bdev.AddChildren(new_bdevs) - return True + return (True, None) def BlockdevRemovechildren(parent_cdev, new_cdevs): @@ -1350,23 +1351,24 @@ def BlockdevRemovechildren(parent_cdev, new_cdevs): """ parent_bdev = _RecursiveFindBD(parent_cdev) if parent_bdev is None: - logging.error("Can't find parent in remove children: %s", parent_cdev) - return False + msg = "Can't find parent device '%s' in remove children" % str(parent_cdev) + logging.error(msg) + return (False, msg) devs = [] for disk in new_cdevs: rpath = disk.StaticDevPath() if rpath is None: bd = _RecursiveFindBD(disk) if bd is None: - logging.error("Can't find dynamic device %s while removing children", - disk) - return False + msg = "Can't find device %s while removing children" % (disk,) + logging.error(msg) + return (False, msg) else: devs.append(bd.dev_path) else: devs.append(rpath) parent_bdev.RemoveChildren(devs) - return True + return (True, None) def BlockdevGetmirrorstatus(disks): @@ -1459,27 +1461,34 @@ def UploadFile(file_name, data, mode, uid, gid, atime, mtime): """ if not os.path.isabs(file_name): - logging.error("Filename passed to UploadFile is not absolute: '%s'", - file_name) - return False + err = "Filename passed to UploadFile is not absolute: '%s'" % file_name + logging.error(err) + return (False, err) - allowed_files = [ + allowed_files = set([ constants.CLUSTER_CONF_FILE, constants.ETC_HOSTS, constants.SSH_KNOWN_HOSTS_FILE, constants.VNC_PASSWORD_FILE, - ] + constants.RAPI_CERT_FILE, + constants.RAPI_USERS_FILE, + ]) + + for hv_name in constants.HYPER_TYPES: + hv_class = hypervisor.GetHypervisor(hv_name) + allowed_files.update(hv_class.GetAncillaryFiles()) if file_name not in allowed_files: - logging.error("Filename passed to UploadFile not in allowed" - " upload targets: '%s'", file_name) - return False + err = "Filename passed to UploadFile not in allowed upload targets: '%s'" \ + % file_name + logging.error(err) + return (False, err) raw_data = _Decompress(data) utils.WriteFile(file_name, data=raw_data, mode=mode, uid=uid, gid=gid, atime=atime, mtime=mtime) - return True + return (True, "success") def WriteSsconfFiles(values): @@ -2006,10 +2015,12 @@ def BlockdevRename(devlist): @return: True if all renames succeeded, False otherwise """ + msgs = [] result = True for disk, unique_id in devlist: dev = _RecursiveFindBD(disk) if dev is None: + msgs.append("Can't find device %s in rename" % str(disk)) result = False continue try: @@ -2024,9 +2035,11 @@ def BlockdevRename(devlist): # cache? for now, we only lose lvm data when we rename, which # is less critical than DRBD or MD except errors.BlockDeviceError, err: + msgs.append("Can't rename device '%s' to '%s': %s" % + (dev, unique_id, err)) logging.exception("Can't rename device '%s' to '%s'", dev, unique_id) result = False - return result + return (result, "; ".join(msgs)) def _TransformFileStorageDir(file_storage_dir): @@ -2437,6 +2450,25 @@ def DrbdWaitSync(nodes_ip, disks): return (not failure, (alldone, min_resync)) +def PowercycleNode(hypervisor_type): + """Hard-powercycle the node. + + Because we need to return first, and schedule the powercycle in the + background, we won't be able to report failures nicely. + + """ + hyper = hypervisor.GetHypervisor(hypervisor_type) + try: + pid = os.fork() + except OSError, err: + # if we can't fork, we'll pretend that we're in the child process + pid = 0 + if pid > 0: + return (True, "Reboot scheduled in 5 seconds") + time.sleep(5) + hyper.PowercycleNode() + + class HooksRunner(object): """Hook runner.