X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/80b898f91857135374733f0e486bb4f8968e735d..320a5daea8f0f9b94de3d2f31a8db5061dce024d:/lib/cmdlib.py diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 5f6c7af..8e0a622 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -703,6 +703,18 @@ def _SupportsOob(cfg, node): return cfg.GetNdParams(node)[constants.ND_OOB_PROGRAM] +def _CopyLockList(names): + """Makes a copy of a list of lock names. + + Handles L{locking.ALL_SET} correctly. + + """ + if names == locking.ALL_SET: + return locking.ALL_SET + else: + return names[:] + + def _GetWantedNodes(lu, nodes): """Returns list of checked and expanded node names. @@ -815,7 +827,7 @@ def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False): # in a nicer way ipolicy[key] = list(value) try: - objects.InstancePolicy.CheckParameterSyntax(ipolicy) + objects.InstancePolicy.CheckParameterSyntax(ipolicy, not group_policy) except errors.ConfigurationError, err: raise errors.OpPrereqError("Invalid instance policy: %s" % err, errors.ECODE_INVAL) @@ -957,9 +969,8 @@ def _RunPostHook(lu, node_name): hm = lu.proc.BuildHooksManager(lu) try: hm.RunPhase(constants.HOOKS_PHASE_POST, nodes=[node_name]) - except: - # pylint: disable=W0702 - lu.LogWarning("Errors occurred running hooks on %s" % node_name) + except Exception, err: # pylint: disable=W0703 + lu.LogWarning("Errors occurred running hooks on %s: %s" % (node_name, err)) def _CheckOutputFields(static, dynamic, selected): @@ -1611,7 +1622,8 @@ def _FindFaultyInstanceDisks(cfg, rpc_runner, instance, node_name, prereq): for dev in instance.disks: cfg.SetDiskID(dev, node_name) - result = rpc_runner.call_blockdev_getmirrorstatus(node_name, instance.disks) + result = rpc_runner.call_blockdev_getmirrorstatus(node_name, (instance.disks, + instance)) result.Raise("Failed to get disk status from node %s" % node_name, prereq=prereq, ecode=errors.ECODE_ENVIRON) @@ -2923,12 +2935,12 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors): node_disks[nname] = disks - # Creating copies as SetDiskID below will modify the objects and that can - # lead to incorrect data returned from nodes - devonly = [dev.Copy() for (_, dev) in disks] - - for dev in devonly: - self.cfg.SetDiskID(dev, nname) + # _AnnotateDiskParams makes already copies of the disks + devonly = [] + for (inst, dev) in disks: + (anno_disk,) = _AnnotateDiskParams(instanceinfo[inst], [dev], self.cfg) + self.cfg.SetDiskID(anno_disk, nname) + devonly.append(anno_disk) node_disks_devonly[nname] = devonly @@ -3213,10 +3225,12 @@ class LUClusterVerifyGroup(LogicalUnit, _VerifyErrors): if master_node not in self.my_node_info: additional_nodes.append(master_node) vf_node_info.append(self.all_node_info[master_node]) - # Add the first vm_capable node we find which is not included + # Add the first vm_capable node we find which is not included, + # excluding the master node (which we already have) for node in absent_nodes: nodeinfo = self.all_node_info[node] - if nodeinfo.vm_capable and not nodeinfo.offline: + if (nodeinfo.vm_capable and not nodeinfo.offline and + node != master_node): additional_nodes.append(node) vf_node_info.append(self.all_node_info[node]) break @@ -4309,6 +4323,9 @@ def _ComputeAncillaryFiles(cluster, redist): if cluster.modify_etc_hosts: files_all.add(constants.ETC_HOSTS) + if cluster.use_external_mip_script: + files_all.add(constants.EXTERNAL_MASTER_SETUP_SCRIPT) + # Files which are optional, these must: # - be present in one other category as well # - either exist or not exist on all nodes of that category (mc, vm all) @@ -4322,10 +4339,6 @@ def _ComputeAncillaryFiles(cluster, redist): if not redist: files_mc.add(constants.CLUSTER_CONF_FILE) - # FIXME: this should also be replicated but Ganeti doesn't support files_mc - # replication - files_mc.add(constants.DEFAULT_MASTER_SETUP_SCRIPT) - # Files which should only be on VM-capable nodes files_vm = set(filename for hv_name in cluster.enabled_hypervisors @@ -4366,7 +4379,8 @@ def _RedistributeAncillaryFiles(lu, additional_nodes=None, additional_vm=True): master_info = lu.cfg.GetNodeInfo(lu.cfg.GetMasterNode()) online_nodes = lu.cfg.GetOnlineNodeList() - vm_nodes = lu.cfg.GetVmCapableNodeList() + online_set = frozenset(online_nodes) + vm_nodes = list(online_set.intersection(lu.cfg.GetVmCapableNodeList())) if additional_nodes is not None: online_nodes.extend(additional_nodes) @@ -4475,7 +4489,7 @@ def _WaitForSync(lu, instance, disks=None, oneshot=False): max_time = 0 done = True cumul_degraded = False - rstats = lu.rpc.call_blockdev_getmirrorstatus(node, disks) + rstats = lu.rpc.call_blockdev_getmirrorstatus(node, (disks, instance)) msg = rstats.fail_msg if msg: lu.LogWarning("Can't get any data from node %s: %s", node, msg) @@ -6373,10 +6387,12 @@ def _AssembleInstanceDisks(lu, instance, disks=None, ignore_secondaries=False, False, idx) msg = result.fail_msg if msg: + is_offline_secondary = (node in instance.secondary_nodes and + result.offline) lu.proc.LogWarning("Could not prepare block device %s on node %s" " (is_primary=False, pass=1): %s", inst_disk.iv_name, node, msg) - if not ignore_secondaries: + if not (ignore_secondaries or is_offline_secondary): disks_ok = False # FIXME: race condition on drbd migration to primary @@ -6509,7 +6525,7 @@ def _ShutdownInstanceDisks(lu, instance, disks=None, ignore_primary=False): for disk in disks: for node, top_disk in disk.ComputeNodeTree(instance.primary_node): lu.cfg.SetDiskID(top_disk, node) - result = lu.rpc.call_blockdev_shutdown(node, top_disk) + result = lu.rpc.call_blockdev_shutdown(node, (top_disk, instance)) msg = result.fail_msg if msg: lu.LogWarning("Could not shutdown block device %s on node %s: %s", @@ -6982,9 +6998,6 @@ class LUInstanceReinstall(LogicalUnit): "Cannot retrieve locked instance %s" % self.op.instance_name _CheckNodeOnline(self, instance.primary_node, "Instance primary node" " offline, cannot reinstall") - for node in instance.secondary_nodes: - _CheckNodeOnline(self, node, "Instance secondary node offline," - " cannot reinstall") if instance.disk_template == constants.DT_DISKLESS: raise errors.OpPrereqError("Instance '%s' has no disks" % @@ -7097,7 +7110,7 @@ class LUInstanceRecreateDisks(LogicalUnit): elif level == locking.LEVEL_NODE_RES: # Copy node locks self.needed_locks[locking.LEVEL_NODE_RES] = \ - self.needed_locks[locking.LEVEL_NODE][:] + _CopyLockList(self.needed_locks[locking.LEVEL_NODE]) def BuildHooksEnv(self): """Build hooks env. @@ -7369,7 +7382,7 @@ class LUInstanceRemove(LogicalUnit): elif level == locking.LEVEL_NODE_RES: # Copy node locks self.needed_locks[locking.LEVEL_NODE_RES] = \ - self.needed_locks[locking.LEVEL_NODE][:] + _CopyLockList(self.needed_locks[locking.LEVEL_NODE]) def BuildHooksEnv(self): """Build hooks env. @@ -7522,7 +7535,7 @@ class LUInstanceFailover(LogicalUnit): elif level == locking.LEVEL_NODE_RES: # Copy node locks self.needed_locks[locking.LEVEL_NODE_RES] = \ - self.needed_locks[locking.LEVEL_NODE][:] + _CopyLockList(self.needed_locks[locking.LEVEL_NODE]) def BuildHooksEnv(self): """Build hooks env. @@ -7606,7 +7619,7 @@ class LUInstanceMigrate(LogicalUnit): elif level == locking.LEVEL_NODE_RES: # Copy node locks self.needed_locks[locking.LEVEL_NODE_RES] = \ - self.needed_locks[locking.LEVEL_NODE][:] + _CopyLockList(self.needed_locks[locking.LEVEL_NODE]) def BuildHooksEnv(self): """Build hooks env. @@ -7665,7 +7678,7 @@ class LUInstanceMove(LogicalUnit): elif level == locking.LEVEL_NODE_RES: # Copy node locks self.needed_locks[locking.LEVEL_NODE_RES] = \ - self.needed_locks[locking.LEVEL_NODE][:] + _CopyLockList(self.needed_locks[locking.LEVEL_NODE]) def BuildHooksEnv(self): """Build hooks env. @@ -8059,14 +8072,9 @@ class TLMigrateInstance(Tasklet): # check if failover must be forced instead of migration if (not self.cleanup and not self.failover and i_be[constants.BE_ALWAYS_FAILOVER]): - if self.fallback: - self.lu.LogInfo("Instance configured to always failover; fallback" - " to failover") - self.failover = True - else: - raise errors.OpPrereqError("This instance has been configured to" - " always failover, please allow failover", - errors.ECODE_STATE) + self.lu.LogInfo("Instance configured to always failover; fallback" + " to failover") + self.failover = True # check bridge existance _CheckInstanceBridgesExist(self.lu, instance, node=target_node) @@ -8493,7 +8501,7 @@ class TLMigrateInstance(Tasklet): disks = _ExpandCheckDisks(instance, instance.disks) self.feedback_fn("* unmapping instance's disks from %s" % source_node) for disk in disks: - result = self.rpc.call_blockdev_shutdown(source_node, disk) + result = self.rpc.call_blockdev_shutdown(source_node, (disk, instance)) msg = result.fail_msg if msg: logging.error("Migration was successful, but couldn't unmap the" @@ -8883,6 +8891,7 @@ def _WipeDisks(lu, instance): result = lu.rpc.call_blockdev_pause_resume_sync(node, (instance.disks, instance), True) + result.Raise("Failed RPC to node %s for pausing the disk syncing" % node) for idx, success in enumerate(result.payload): if not success: @@ -8930,12 +8939,17 @@ def _WipeDisks(lu, instance): (instance.disks, instance), False) - for idx, success in enumerate(result.payload): - if not success: - lu.LogWarning("Resume sync of disk %d failed, please have a" - " look at the status and troubleshoot the issue", idx) - logging.warn("resume-sync of instance %s for disks %d failed", - instance.name, idx) + if result.fail_msg: + lu.LogWarning("RPC call to %s for resuming disk syncing failed," + " please have a look at the status and troubleshoot" + " the issue: %s", node, result.fail_msg) + else: + for idx, success in enumerate(result.payload): + if not success: + lu.LogWarning("Resume sync of disk %d failed, please have a" + " look at the status and troubleshoot the issue", idx) + logging.warn("resume-sync of instance %s for disks %d failed", + instance.name, idx) def _CreateDisks(lu, instance, to_skip=None, target_node=None): @@ -9004,18 +9018,20 @@ def _RemoveDisks(lu, instance, target_node=None, ignore_failures=False): all_result = True ports_to_release = set() - for (idx, device) in enumerate(instance.disks): + anno_disks = _AnnotateDiskParams(instance, instance.disks, lu.cfg) + for (idx, device) in enumerate(anno_disks): if target_node: edata = [(target_node, device)] else: edata = device.ComputeNodeTree(instance.primary_node) for node, disk in edata: lu.cfg.SetDiskID(disk, node) - msg = lu.rpc.call_blockdev_remove(node, disk).fail_msg - if msg: + result = lu.rpc.call_blockdev_remove(node, disk) + if result.fail_msg: lu.LogWarning("Could not remove disk %s on node %s," - " continuing anyway: %s", idx, node, msg) - all_result = False + " continuing anyway: %s", idx, node, result.fail_msg) + if not (result.offline and node != instance.primary_node): + all_result = False # if this is a DRBD disk, return its port to the pool if device.dev_type in constants.LDS_DRBD: @@ -9073,7 +9089,7 @@ def _ComputeDiskSizePerVG(disk_template, disks): def _ComputeDiskSize(disk_template, disks): - """Compute disk size requirements in the volume group + """Compute disk size requirements according to disk template """ # Required free disk space as a function of disk and swap space @@ -9083,10 +9099,10 @@ def _ComputeDiskSize(disk_template, disks): # 128 MB are added for drbd metadata for each disk constants.DT_DRBD8: sum(d[constants.IDISK_SIZE] + DRBD_META_SIZE for d in disks), - constants.DT_FILE: None, - constants.DT_SHARED_FILE: 0, + constants.DT_FILE: sum(d[constants.IDISK_SIZE] for d in disks), + constants.DT_SHARED_FILE: sum(d[constants.IDISK_SIZE] for d in disks), constants.DT_BLOCK: 0, - constants.DT_RBD: 0, + constants.DT_RBD: sum(d[constants.IDISK_SIZE] for d in disks), } if disk_template not in req_size_dict: @@ -11159,7 +11175,8 @@ class TLReplaceDisks(Tasklet): for idx, dev in enumerate(self.instance.disks): self.lu.LogInfo("Shutting down drbd for disk/%d on old node" % idx) self.cfg.SetDiskID(dev, self.target_node) - msg = self.rpc.call_blockdev_shutdown(self.target_node, dev).fail_msg + msg = self.rpc.call_blockdev_shutdown(self.target_node, + (dev, self.instance)).fail_msg if msg: self.lu.LogWarning("Failed to shutdown drbd for disk/%d on old" "node: %s" % (idx, msg), @@ -11575,7 +11592,7 @@ class LUInstanceGrowDisk(LogicalUnit): elif level == locking.LEVEL_NODE_RES: # Copy node locks self.needed_locks[locking.LEVEL_NODE_RES] = \ - self.needed_locks[locking.LEVEL_NODE][:] + _CopyLockList(self.needed_locks[locking.LEVEL_NODE]) def BuildHooksEnv(self): """Build hooks env. @@ -12241,7 +12258,7 @@ class LUInstanceSetParams(LogicalUnit): elif level == locking.LEVEL_NODE_RES and self.op.disk_template: # Copy node locks self.needed_locks[locking.LEVEL_NODE_RES] = \ - self.needed_locks[locking.LEVEL_NODE][:] + _CopyLockList(self.needed_locks[locking.LEVEL_NODE]) def BuildHooksEnv(self): """Build hooks env. @@ -12690,8 +12707,8 @@ class LUInstanceSetParams(LogicalUnit): snode = instance.secondary_nodes[0] feedback_fn("Converting template to plain") - old_disks = instance.disks - new_disks = [d.children[0] for d in old_disks] + old_disks = _AnnotateDiskParams(instance, instance.disks, self.cfg) + new_disks = [d.children[0] for d in instance.disks] # copy over size and mode for parent, child in zip(old_disks, new_disks): @@ -12781,7 +12798,8 @@ class LUInstanceSetParams(LogicalUnit): """Removes a disk. """ - for node, disk in root.ComputeNodeTree(self.instance.primary_node): + (anno_disk,) = _AnnotateDiskParams(self.instance, [root], self.cfg) + for node, disk in anno_disk.ComputeNodeTree(self.instance.primary_node): self.cfg.SetDiskID(disk, node) msg = self.rpc.call_blockdev_remove(node, disk).fail_msg if msg: @@ -13623,7 +13641,7 @@ class LUGroupAdd(LogicalUnit): cluster = self.cfg.GetClusterInfo() full_ipolicy = cluster.SimpleFillIPolicy(self.op.ipolicy) try: - objects.InstancePolicy.CheckParameterSyntax(full_ipolicy) + objects.InstancePolicy.CheckParameterSyntax(full_ipolicy, False) except errors.ConfigurationError, err: raise errors.OpPrereqError("Invalid instance policy: %s" % err, errors.ECODE_INVAL) @@ -13962,7 +13980,7 @@ class LUGroupSetParams(LogicalUnit): if self.op.ndparams: new_ndparams = _GetUpdatedParams(self.group.ndparams, self.op.ndparams) - utils.ForceDictType(self.op.ndparams, constants.NDS_PARAMETER_TYPES) + utils.ForceDictType(new_ndparams, constants.NDS_PARAMETER_TYPES) self.new_ndparams = new_ndparams if self.op.diskparams: @@ -15284,6 +15302,7 @@ class LUTestAllocator(NoHooksLU): nics=self.op.nics, vcpus=self.op.vcpus, hypervisor=self.op.hypervisor, + spindle_use=self.op.spindle_use, ) elif self.op.mode == constants.IALLOCATOR_MODE_RELOC: ial = IAllocator(self.cfg, self.rpc,