Revision 61f232ec lib/cmdlib.py
b/lib/cmdlib.py | ||
---|---|---|
6350 | 6350 |
|
6351 | 6351 |
|
6352 | 6352 |
def _AssembleInstanceDisks(lu, instance, disks=None, ignore_secondaries=False, |
6353 |
ignore_size=False): |
|
6353 |
ignore_size=False, check=True):
|
|
6354 | 6354 |
"""Prepare the block devices for an instance. |
6355 | 6355 |
|
6356 | 6356 |
This sets up the block devices on all nodes. |
... | ... | |
6376 | 6376 |
device_info = [] |
6377 | 6377 |
disks_ok = True |
6378 | 6378 |
iname = instance.name |
6379 |
disks = _ExpandCheckDisks(instance, disks) |
|
6379 |
if check: |
|
6380 |
disks = _ExpandCheckDisks(instance, disks) |
|
6380 | 6381 |
|
6381 | 6382 |
# With the two passes mechanism we try to reduce the window of |
6382 | 6383 |
# opportunity for the race condition of switching DRBD to primary |
... | ... | |
8734 | 8735 |
results.append("%s%s" % (new_id, val)) |
8735 | 8736 |
return results |
8736 | 8737 |
|
8738 |
def _GetPCIInfo(lu, dev_type): |
|
8739 |
|
|
8740 |
if lu.op.hotplug: |
|
8741 |
if hasattr(lu, 'hotplug_info'): |
|
8742 |
info = lu.hotplug_info |
|
8743 |
elif hasattr(lu, 'instance') and hasattr(lu.instance, 'hotplug_info'): |
|
8744 |
return lu.cfg.GetPCIInfo(lu.instance.name, dev_type) |
|
8745 |
|
|
8746 |
if info: |
|
8747 |
idx = getattr(info, dev_type) |
|
8748 |
setattr(info, dev_type, idx+1) |
|
8749 |
pci = info.pci_pool.pop() |
|
8750 |
return idx, pci |
|
8751 |
|
|
8752 |
return None, None |
|
8753 |
|
|
8737 | 8754 |
|
8738 | 8755 |
def _GenerateDRBD8Branch(lu, primary, secondary, size, vgnames, names, |
8739 | 8756 |
iv_name, p_minor, s_minor): |
... | ... | |
8750 | 8767 |
dev_meta = objects.Disk(dev_type=constants.LD_LV, size=DRBD_META_SIZE, |
8751 | 8768 |
logical_id=(vgnames[1], names[1]), |
8752 | 8769 |
params={}) |
8753 |
drbd_dev = objects.Disk(dev_type=constants.LD_DRBD8, size=size, |
|
8770 |
|
|
8771 |
disk_idx, pci = _GetPCIInfo(lu, 'disks') |
|
8772 |
drbd_dev = objects.Disk(idx=disk_idx, pci=pci, |
|
8773 |
dev_type=constants.LD_DRBD8, size=size, |
|
8754 | 8774 |
logical_id=(primary, secondary, port, |
8755 | 8775 |
p_minor, s_minor, |
8756 | 8776 |
shared_secret), |
... | ... | |
8859 | 8879 |
size = disk[constants.IDISK_SIZE] |
8860 | 8880 |
feedback_fn("* disk %s, size %s" % |
8861 | 8881 |
(disk_index, utils.FormatUnit(size, "h"))) |
8882 |
|
|
8883 |
disk_idx, pci = _GetPCIInfo(lu, 'disks') |
|
8884 |
|
|
8862 | 8885 |
disks.append(objects.Disk(dev_type=dev_type, size=size, |
8863 | 8886 |
logical_id=logical_id_fn(idx, disk_index, disk), |
8864 | 8887 |
iv_name="disk/%d" % disk_index, |
8865 | 8888 |
mode=disk[constants.IDISK_MODE], |
8866 |
params={})) |
|
8889 |
params={}, idx=disk_idx, pci=pci))
|
|
8867 | 8890 |
|
8868 | 8891 |
return disks |
8869 | 8892 |
|
... | ... | |
9746 | 9769 |
if self.op.identify_defaults: |
9747 | 9770 |
self._RevertToDefaults(cluster) |
9748 | 9771 |
|
9772 |
self.hotplug_info = None |
|
9773 |
if self.op.hotplug: |
|
9774 |
self.hotplug_info = objects.HotplugInfo(disks=0, nics=0, |
|
9775 |
pci_pool=list(range(16,32))) |
|
9749 | 9776 |
# NIC buildup |
9750 | 9777 |
self.nics = [] |
9751 | 9778 |
for idx, nic in enumerate(self.op.nics): |
... | ... | |
9805 | 9832 |
|
9806 | 9833 |
check_params = cluster.SimpleFillNIC(nicparams) |
9807 | 9834 |
objects.NIC.CheckParameterSyntax(check_params) |
9808 |
self.nics.append(objects.NIC(mac=mac, ip=nic_ip, nicparams=nicparams)) |
|
9835 |
nic_idx, pci = _GetPCIInfo(self, 'nics') |
|
9836 |
self.nics.append(objects.NIC(idx=nic_idx, pci=pci, |
|
9837 |
mac=mac, ip=nic_ip, |
|
9838 |
nicparams=check_params)) |
|
9809 | 9839 |
|
9810 | 9840 |
# disk checks/pre-build |
9811 | 9841 |
default_vg = self.cfg.GetVGName() |
... | ... | |
10089 | 10119 |
hvparams=self.op.hvparams, |
10090 | 10120 |
hypervisor=self.op.hypervisor, |
10091 | 10121 |
osparams=self.op.osparams, |
10122 |
hotplug_info=self.hotplug_info, |
|
10092 | 10123 |
) |
10093 | 10124 |
|
10094 | 10125 |
if self.op.tags: |
... | ... | |
12054 | 12085 |
if remove_fn is not None: |
12055 | 12086 |
remove_fn(absidx, item, private) |
12056 | 12087 |
|
12088 |
#TODO: include a hotplugged msg in changes |
|
12057 | 12089 |
changes = [("%s/%s" % (kind, absidx), "remove")] |
12058 | 12090 |
|
12059 | 12091 |
assert container[absidx] == item |
12060 | 12092 |
del container[absidx] |
12061 | 12093 |
elif op == constants.DDM_MODIFY: |
12062 | 12094 |
if modify_fn is not None: |
12095 |
#TODO: include a hotplugged msg in changes |
|
12063 | 12096 |
changes = modify_fn(absidx, item, params, private) |
12097 |
|
|
12064 | 12098 |
else: |
12065 | 12099 |
raise errors.ProgrammerError("Unhandled operation '%s'" % op) |
12066 | 12100 |
|
... | ... | |
12362 | 12396 |
" in cluster" % mac, |
12363 | 12397 |
errors.ECODE_NOTUNIQUE) |
12364 | 12398 |
|
12399 |
logging.info("new_params %s", new_params) |
|
12400 |
logging.info("new_filled_params %s", new_filled_params) |
|
12365 | 12401 |
private.params = new_params |
12366 | 12402 |
private.filled = new_filled_params |
12367 | 12403 |
|
... | ... | |
12385 | 12421 |
# Prepare disk/NIC modifications |
12386 | 12422 |
self.diskmod = PrepareContainerMods(self.op.disks, None) |
12387 | 12423 |
self.nicmod = PrepareContainerMods(self.op.nics, _InstNicModPrivate) |
12424 |
logging.info("nicmod %s", self.nicmod) |
|
12388 | 12425 |
|
12389 | 12426 |
# OS change |
12390 | 12427 |
if self.op.os_name and not self.op.force: |
... | ... | |
12616 | 12653 |
" (%d), cannot add more" % constants.MAX_NICS, |
12617 | 12654 |
errors.ECODE_STATE) |
12618 | 12655 |
|
12656 |
|
|
12619 | 12657 |
# Verify disk changes (operating on a copy) |
12620 | 12658 |
disks = instance.disks[:] |
12621 |
ApplyContainerMods("disk", disks, None, self.diskmod, None, None, None) |
|
12659 |
ApplyContainerMods("disk", disks, None, self.diskmod, |
|
12660 |
None, None, None) |
|
12622 | 12661 |
if len(disks) > constants.MAX_DISKS: |
12623 | 12662 |
raise errors.OpPrereqError("Instance has too many disks (%d), cannot add" |
12624 | 12663 |
" more" % constants.MAX_DISKS, |
... | ... | |
12637 | 12676 |
# Operate on copies as this is still in prereq |
12638 | 12677 |
nics = [nic.Copy() for nic in instance.nics] |
12639 | 12678 |
ApplyContainerMods("NIC", nics, self._nic_chgdesc, self.nicmod, |
12640 |
self._CreateNewNic, self._ApplyNicMods, None) |
|
12679 |
self._CreateNewNic, self._ApplyNicMods, |
|
12680 |
self._RemoveNic) |
|
12641 | 12681 |
self._new_nics = nics |
12642 | 12682 |
else: |
12643 | 12683 |
self._new_nics = None |
12644 | 12684 |
|
12685 |
|
|
12645 | 12686 |
def _ConvertPlainToDrbd(self, feedback_fn): |
12646 | 12687 |
"""Converts an instance from plain to drbd. |
12647 | 12688 |
|
... | ... | |
12789 | 12830 |
self.LogWarning("Failed to create volume %s (%s) on node '%s': %s", |
12790 | 12831 |
disk.iv_name, disk, node, err) |
12791 | 12832 |
|
12833 |
if self.op.hotplug and disk.pci: |
|
12834 |
disk_ok, device_info = _AssembleInstanceDisks(self, self.instance, |
|
12835 |
[disk], check=False) |
|
12836 |
_, _, dev_path = device_info[0] |
|
12837 |
result = self.rpc.call_hot_add_disk(self.instance.primary_node, |
|
12838 |
self.instance, disk, dev_path, idx) |
|
12792 | 12839 |
return (disk, [ |
12793 | 12840 |
("disk/%d" % idx, "add:size=%s,mode=%s" % (disk.size, disk.mode)), |
12794 | 12841 |
]) |
... | ... | |
12808 | 12855 |
"""Removes a disk. |
12809 | 12856 |
|
12810 | 12857 |
""" |
12858 |
#TODO: log warning in case hotplug is not possible |
|
12859 |
# handle errors |
|
12860 |
if root.pci and not self.op.hotplug: |
|
12861 |
raise errors.OpPrereqError("Cannot remove a disk that has" |
|
12862 |
" been hotplugged" |
|
12863 |
" without removing it with hotplug", |
|
12864 |
errors.ECODE_INVAL) |
|
12865 |
if self.op.hotplug and root.pci: |
|
12866 |
self.rpc.call_hot_del_disk(self.instance.primary_node, |
|
12867 |
self.instance, root, idx) |
|
12868 |
_ShutdownInstanceDisks(self, self.instance, [root]) |
|
12869 |
self.cfg.UpdatePCIInfo(self.instance.name, root.pci) |
|
12870 |
|
|
12811 | 12871 |
(anno_disk,) = _AnnotateDiskParams(self.instance, [root], self.cfg) |
12812 | 12872 |
for node, disk in anno_disk.ComputeNodeTree(self.instance.primary_node): |
12813 | 12873 |
self.cfg.SetDiskID(disk, node) |
... | ... | |
12820 | 12880 |
if root.dev_type in constants.LDS_DRBD: |
12821 | 12881 |
self.cfg.AddTcpUdpPort(root.logical_id[2]) |
12822 | 12882 |
|
12823 |
@staticmethod |
|
12824 |
def _CreateNewNic(idx, params, private): |
|
12883 |
def _CreateNewNic(self, idx, params, private): |
|
12825 | 12884 |
"""Creates data structure for a new network interface. |
12826 | 12885 |
|
12827 | 12886 |
""" |
12828 | 12887 |
mac = params[constants.INIC_MAC] |
12829 | 12888 |
ip = params.get(constants.INIC_IP, None) |
12830 |
nicparams = private.params |
|
12831 |
|
|
12832 |
return (objects.NIC(mac=mac, ip=ip, nicparams=nicparams), [ |
|
12889 |
#TODO: not private.filled?? can a nic be saved without nicparams?? |
|
12890 |
nicparams = private.filled |
|
12891 |
|
|
12892 |
nic = objects.NIC(mac=mac, ip=ip, nicparams=nicparams) |
|
12893 |
|
|
12894 |
#TODO: log warning in case hotplug is not possible |
|
12895 |
# handle errors |
|
12896 |
# return changes |
|
12897 |
if self.op.hotplug: |
|
12898 |
nic_idx, pci = _GetPCIInfo(self, 'nics') |
|
12899 |
nic.idx = nic_idx |
|
12900 |
nic.pci = pci |
|
12901 |
result = self.rpc.call_hot_add_nic(self.instance.primary_node, |
|
12902 |
self.instance, nic, idx) |
|
12903 |
desc = [ |
|
12833 | 12904 |
("nic.%d" % idx, |
12834 | 12905 |
"add:mac=%s,ip=%s,mode=%s,link=%s" % |
12835 | 12906 |
(mac, ip, private.filled[constants.NIC_MODE], |
12836 | 12907 |
private.filled[constants.NIC_LINK])), |
12837 |
]) |
|
12908 |
] |
|
12909 |
return (nic, desc) |
|
12838 | 12910 |
|
12839 |
@staticmethod |
|
12840 |
def _ApplyNicMods(idx, nic, params, private): |
|
12911 |
def _ApplyNicMods(self, idx, nic, params, private): |
|
12841 | 12912 |
"""Modifies a network interface. |
12842 | 12913 |
|
12843 | 12914 |
""" |
... | ... | |
12854 | 12925 |
for (key, val) in params.items(): |
12855 | 12926 |
changes.append(("nic.%s/%d" % (key, idx), val)) |
12856 | 12927 |
|
12928 |
#TODO: log warning in case hotplug is not possible |
|
12929 |
# handle errors |
|
12930 |
if self.op.hotplug and nic.pci: |
|
12931 |
self.rpc.call_hot_del_nic(self.instance.primary_node, |
|
12932 |
self.instance, nic, idx) |
|
12933 |
result = self.rpc.call_hot_add_nic(self.instance.primary_node, |
|
12934 |
self.instance, nic, idx) |
|
12857 | 12935 |
return changes |
12858 | 12936 |
|
12937 |
def _RemoveNic(self, idx, nic, private): |
|
12938 |
if nic.pci and not self.op.hotplug: |
|
12939 |
raise errors.OpPrereqError("Cannot remove a nic that has been hotplugged" |
|
12940 |
" without removing it with hotplug", |
|
12941 |
errors.ECODE_INVAL) |
|
12942 |
#TODO: log warning in case hotplug is not possible |
|
12943 |
# handle errors |
|
12944 |
if self.op.hotplug and nic.pci: |
|
12945 |
self.rpc.call_hot_del_nic(self.instance.primary_node, |
|
12946 |
self.instance, nic, idx) |
|
12947 |
self.cfg.UpdatePCIInfo(self.instance.name, nic.pci) |
|
12948 |
|
|
12949 |
|
|
12859 | 12950 |
def Exec(self, feedback_fn): |
12860 | 12951 |
"""Modifies an instance. |
12861 | 12952 |
|
Also available in: Unified diff