diff --git a/lib/cmdlib.py b/lib/cmdlib.py index a2cbf2fa4c968792ea2e9e1aec146eaea94349b7..47a6e83886badc891d661484409470afb13b3d74 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -1767,6 +1767,17 @@ def _GetDefaultIAllocator(cfg, iallocator): return iallocator +def _InstanceRunning(lu, instance): + """Return True if instance is running else False.""" + + remote_info = lu.rpc.call_instance_info(instance.primary_node, + instance.name, + instance.hypervisor) + remote_info.Raise("Error checking node %s" % instance.primary_node) + instance_running = bool(remote_info.payload) + return instance_running + + class LUClusterPostInit(LogicalUnit): """Logical unit for running hooks after cluster initialization. @@ -8964,7 +8975,7 @@ def _GetPCIInfo(lu, dev_type): return idx, pci # case of InstanceSetParams() elif lu.instance.hotplug_info is not None: - idx, pci = lu.cfg.GetPCIInfo(lu.instance.name, dev_type) + idx, pci = lu.cfg.GetPCIInfo(lu.instance, dev_type) lu.LogInfo("Choosing pci slot %d" % pci) return idx, pci @@ -13291,7 +13302,7 @@ class LUInstanceSetParams(LogicalUnit): self.LogWarning("Failed to create volume %s (%s) on node '%s': %s", disk.iv_name, disk, node, err) - if self.op.hotplug and disk.pci: + if self.op.hotplug and disk.pci and _InstanceRunning(self, self.instance): self.LogInfo("Trying to hotplug device.") _, device_info = _AssembleInstanceDisks(self, self.instance, [disk], check=False) @@ -13326,11 +13337,12 @@ class LUInstanceSetParams(LogicalUnit): " without removing it with hotplug", errors.ECODE_INVAL) if self.op.hotplug and root.pci: - self.LogInfo("Trying to hotplug device.") - self.rpc.call_hot_del_disk(self.instance.primary_node, - self.instance, root, idx) - _ShutdownInstanceDisks(self, self.instance, [root]) - self.cfg.UpdatePCIInfo(self.instance.name, root.pci) + if _InstanceRunning(self, self.instance): + self.LogInfo("Trying to hotplug device.") + self.rpc.call_hot_del_disk(self.instance.primary_node, + self.instance, root, idx) + _ShutdownInstanceDisks(self, self.instance, [root]) + self.cfg.UpdatePCIInfo(self.instance, root.pci) (anno_disk,) = _AnnotateDiskParams(self.instance, [root], self.cfg) for node, disk in anno_disk.ComputeNodeTree(self.instance.primary_node): @@ -13360,10 +13372,8 @@ class LUInstanceSetParams(LogicalUnit): # handle errors # return changes if self.op.hotplug: - nic_idx, pci = _GetPCIInfo(self, 'nics') - if pci is not None: - nic.idx = nic_idx - nic.pci = pci + nic.idx, nic.pci = _GetPCIInfo(self, 'nics') + if nic.pci is not None and _InstanceRunning(self, self.instance): self.rpc.call_hot_add_nic(self.instance.primary_node, self.instance, nic, idx) desc = [ @@ -13394,7 +13404,7 @@ class LUInstanceSetParams(LogicalUnit): #TODO: log warning in case hotplug is not possible # handle errors - if self.op.hotplug and nic.pci: + if self.op.hotplug and nic.pci and _InstanceRunning(self, self.instance): self.LogInfo("Trying to hotplug device.") self.rpc.call_hot_del_nic(self.instance.primary_node, self.instance, nic, idx) @@ -13410,10 +13420,11 @@ class LUInstanceSetParams(LogicalUnit): #TODO: log warning in case hotplug is not possible # handle errors if self.op.hotplug and nic.pci: - self.LogInfo("Trying to hotplug device.") - self.rpc.call_hot_del_nic(self.instance.primary_node, - self.instance, nic, idx) - self.cfg.UpdatePCIInfo(self.instance.name, nic.pci) + if _InstanceRunning(self, self.instance): + self.LogInfo("Trying to hotplug device.") + self.rpc.call_hot_del_nic(self.instance.primary_node, + self.instance, nic, idx) + self.cfg.UpdatePCIInfo(self.instance, nic.pci) def Exec(self, feedback_fn): diff --git a/lib/config.py b/lib/config.py index d7a6c8addbae5fc5881469f9fbdd8bc2b47b5d39..92b73e2141cc097d4de20267f8c7593dcd5f1f89 100644 --- a/lib/config.py +++ b/lib/config.py @@ -402,12 +402,11 @@ class ConfigWriter: if net_uuid: return self._UnlockedReserveIp(net_uuid, address, ec_id) - @locking.ssynchronized(_config_lock, shared=1) - def GetPCIInfo(self, instance_name, dev_type): + @locking.ssynchronized(_config_lock) + def GetPCIInfo(self, instance, dev_type): - instance = self._UnlockedGetInstanceInfo(instance_name) if not instance.hotplug_info: - return None, None + return None, None idx = getattr(instance.hotplug_info, dev_type) setattr(instance.hotplug_info, dev_type, idx+1) pci = instance.hotplug_info.pci_pool.pop() @@ -415,11 +414,12 @@ class ConfigWriter: return idx, pci - @locking.ssynchronized(_config_lock, shared=1) - def UpdatePCIInfo(self, instance_name, pci_slot): + @locking.ssynchronized(_config_lock) + def UpdatePCIInfo(self, instance, pci_slot): - instance = self._UnlockedGetInstanceInfo(instance_name) if instance.hotplug_info: + logging.info("Releasing PCI slot %d for instance %s", + pci_slot, instance.name) instance.hotplug_info.pci_pool.append(pci_slot) self._WriteConfig()