Revision 08db7c5c lib/cmdlib.py
b/lib/cmdlib.py | ||
---|---|---|
3141 | 3141 |
|
3142 | 3142 |
def _GenerateDiskTemplate(lu, template_name, |
3143 | 3143 |
instance_name, primary_node, |
3144 |
secondary_nodes, disk_sz, swap_sz,
|
|
3144 |
secondary_nodes, disk_info,
|
|
3145 | 3145 |
file_storage_dir, file_driver): |
3146 | 3146 |
"""Generate the entire disk layout for a given template type. |
3147 | 3147 |
|
... | ... | |
3149 | 3149 |
#TODO: compute space requirements |
3150 | 3150 |
|
3151 | 3151 |
vgname = lu.cfg.GetVGName() |
3152 |
disk_count = len(disk_info) |
|
3153 |
disks = [] |
|
3152 | 3154 |
if template_name == constants.DT_DISKLESS: |
3153 |
disks = []
|
|
3155 |
pass
|
|
3154 | 3156 |
elif template_name == constants.DT_PLAIN: |
3155 | 3157 |
if len(secondary_nodes) != 0: |
3156 | 3158 |
raise errors.ProgrammerError("Wrong template configuration") |
3157 | 3159 |
|
3158 |
names = _GenerateUniqueNames(lu, [".sda", ".sdb"]) |
|
3159 |
sda_dev = objects.Disk(dev_type=constants.LD_LV, size=disk_sz, |
|
3160 |
logical_id=(vgname, names[0]), |
|
3161 |
iv_name = "sda") |
|
3162 |
sdb_dev = objects.Disk(dev_type=constants.LD_LV, size=swap_sz, |
|
3163 |
logical_id=(vgname, names[1]), |
|
3164 |
iv_name = "sdb") |
|
3165 |
disks = [sda_dev, sdb_dev] |
|
3160 |
names = _GenerateUniqueNames(lu, [".disk%d" % i |
|
3161 |
for i in range(disk_count)]) |
|
3162 |
for idx, disk in enumerate(disk_info): |
|
3163 |
disk_dev = objects.Disk(dev_type=constants.LD_LV, size=disk["size"], |
|
3164 |
logical_id=(vgname, names[idx]), |
|
3165 |
iv_name = "disk/%d" % idx) |
|
3166 |
disks.append(disk_dev) |
|
3166 | 3167 |
elif template_name == constants.DT_DRBD8: |
3167 | 3168 |
if len(secondary_nodes) != 1: |
3168 | 3169 |
raise errors.ProgrammerError("Wrong template configuration") |
3169 | 3170 |
remote_node = secondary_nodes[0] |
3170 |
(minor_pa, minor_pb, |
|
3171 |
minor_sa, minor_sb) = lu.cfg.AllocateDRBDMinor( |
|
3172 |
[primary_node, primary_node, remote_node, remote_node], instance_name) |
|
3173 |
|
|
3174 |
names = _GenerateUniqueNames(lu, [".sda_data", ".sda_meta", |
|
3175 |
".sdb_data", ".sdb_meta"]) |
|
3176 |
drbd_sda_dev = _GenerateDRBD8Branch(lu, primary_node, remote_node, |
|
3177 |
disk_sz, names[0:2], "sda", |
|
3178 |
minor_pa, minor_sa) |
|
3179 |
drbd_sdb_dev = _GenerateDRBD8Branch(lu, primary_node, remote_node, |
|
3180 |
swap_sz, names[2:4], "sdb", |
|
3181 |
minor_pb, minor_sb) |
|
3182 |
disks = [drbd_sda_dev, drbd_sdb_dev] |
|
3171 |
minors = lu.cfg.AllocateDRBDMinor( |
|
3172 |
[primary_node, remote_node] * len(disk_info), instance_name) |
|
3173 |
|
|
3174 |
names = _GenerateUniqueNames(lu, |
|
3175 |
[".disk%d_%s" % (i, s) |
|
3176 |
for i in range(disk_count) |
|
3177 |
for s in ("data", "meta") |
|
3178 |
]) |
|
3179 |
for idx, disk in enumerate(disk_info): |
|
3180 |
disk_dev = _GenerateDRBD8Branch(lu, primary_node, remote_node, |
|
3181 |
disk["size"], names[idx*2:idx*2+2], |
|
3182 |
"disk/%d" % idx, |
|
3183 |
minors[idx*2], minors[idx*2+1]) |
|
3184 |
disks.append(disk_dev) |
|
3183 | 3185 |
elif template_name == constants.DT_FILE: |
3184 | 3186 |
if len(secondary_nodes) != 0: |
3185 | 3187 |
raise errors.ProgrammerError("Wrong template configuration") |
3186 | 3188 |
|
3187 |
file_sda_dev = objects.Disk(dev_type=constants.LD_FILE, size=disk_sz, |
|
3188 |
iv_name="sda", logical_id=(file_driver, |
|
3189 |
"%s/sda" % file_storage_dir)) |
|
3190 |
file_sdb_dev = objects.Disk(dev_type=constants.LD_FILE, size=swap_sz, |
|
3191 |
iv_name="sdb", logical_id=(file_driver, |
|
3192 |
"%s/sdb" % file_storage_dir)) |
|
3193 |
disks = [file_sda_dev, file_sdb_dev] |
|
3189 |
for idx, disk in enumerate(disk_info): |
|
3190 |
|
|
3191 |
disk_dev = objects.Disk(dev_type=constants.LD_FILE, size=disk["size"], |
|
3192 |
iv_name="disk/%d" % idx, |
|
3193 |
logical_id=(file_driver, |
|
3194 |
"%s/disk%d" % (file_storage_dir, |
|
3195 |
idx))) |
|
3196 |
disks.append(disk_dev) |
|
3194 | 3197 |
else: |
3195 | 3198 |
raise errors.ProgrammerError("Invalid disk template '%s'" % template_name) |
3196 | 3199 |
return disks |
... | ... | |
3285 | 3288 |
return result |
3286 | 3289 |
|
3287 | 3290 |
|
3288 |
def _ComputeDiskSize(disk_template, disk_size, swap_size):
|
|
3291 |
def _ComputeDiskSize(disk_template, disks):
|
|
3289 | 3292 |
"""Compute disk size requirements in the volume group |
3290 | 3293 |
|
3291 | 3294 |
This is currently hard-coded for the two-drive layout. |
... | ... | |
3294 | 3297 |
# Required free disk space as a function of disk and swap space |
3295 | 3298 |
req_size_dict = { |
3296 | 3299 |
constants.DT_DISKLESS: None, |
3297 |
constants.DT_PLAIN: disk_size + swap_size,
|
|
3298 |
# 256 MB are added for drbd metadata, 128MB for each drbd device
|
|
3299 |
constants.DT_DRBD8: disk_size + swap_size + 256,
|
|
3300 |
constants.DT_PLAIN: sum(d["size"] for d in disks),
|
|
3301 |
# 128 MB are added for drbd metadata for each disk
|
|
3302 |
constants.DT_DRBD8: sum(d["size"] + 128 for d in disks),
|
|
3300 | 3303 |
constants.DT_FILE: None, |
3301 | 3304 |
} |
3302 | 3305 |
|
... | ... | |
3343 | 3346 |
""" |
3344 | 3347 |
HPATH = "instance-add" |
3345 | 3348 |
HTYPE = constants.HTYPE_INSTANCE |
3346 |
_OP_REQP = ["instance_name", "disk_size",
|
|
3347 |
"disk_template", "swap_size", "mode", "start",
|
|
3348 |
"wait_for_sync", "ip_check", "mac",
|
|
3349 |
_OP_REQP = ["instance_name", "disks", "disk_template",
|
|
3350 |
"mode", "start", |
|
3351 |
"wait_for_sync", "ip_check", "nics",
|
|
3349 | 3352 |
"hvparams", "beparams"] |
3350 | 3353 |
REQ_BGL = False |
3351 | 3354 |
|
... | ... | |
3418 | 3421 |
|
3419 | 3422 |
self.add_locks[locking.LEVEL_INSTANCE] = instance_name |
3420 | 3423 |
|
3421 |
# ip validity checks |
|
3422 |
ip = getattr(self.op, "ip", None) |
|
3423 |
if ip is None or ip.lower() == "none": |
|
3424 |
inst_ip = None |
|
3425 |
elif ip.lower() == constants.VALUE_AUTO: |
|
3426 |
inst_ip = hostname1.ip |
|
3427 |
else: |
|
3428 |
if not utils.IsValidIP(ip): |
|
3429 |
raise errors.OpPrereqError("given IP address '%s' doesn't look" |
|
3430 |
" like a valid IP" % ip) |
|
3431 |
inst_ip = ip |
|
3432 |
self.inst_ip = self.op.ip = inst_ip |
|
3424 |
# NIC buildup |
|
3425 |
self.nics = [] |
|
3426 |
for nic in self.op.nics: |
|
3427 |
# ip validity checks |
|
3428 |
ip = nic.get("ip", None) |
|
3429 |
if ip is None or ip.lower() == "none": |
|
3430 |
nic_ip = None |
|
3431 |
elif ip.lower() == constants.VALUE_AUTO: |
|
3432 |
nic_ip = hostname1.ip |
|
3433 |
else: |
|
3434 |
if not utils.IsValidIP(ip): |
|
3435 |
raise errors.OpPrereqError("Given IP address '%s' doesn't look" |
|
3436 |
" like a valid IP" % ip) |
|
3437 |
nic_ip = ip |
|
3438 |
|
|
3439 |
# MAC address verification |
|
3440 |
mac = nic.get("mac", constants.VALUE_AUTO) |
|
3441 |
if mac not in (constants.VALUE_AUTO, constants.VALUE_GENERATE): |
|
3442 |
if not utils.IsValidMac(mac.lower()): |
|
3443 |
raise errors.OpPrereqError("Invalid MAC address specified: %s" % |
|
3444 |
mac) |
|
3445 |
# bridge verification |
|
3446 |
bridge = nic.get("bridge", self.cfg.GetDefBridge()) |
|
3447 |
self.nics.append(objects.NIC(mac=mac, ip=nic_ip, bridge=bridge)) |
|
3448 |
|
|
3449 |
# disk checks/pre-build |
|
3450 |
self.disks = [] |
|
3451 |
for disk in self.op.disks: |
|
3452 |
mode = disk.get("mode", constants.DISK_RDWR) |
|
3453 |
if mode not in constants.DISK_ACCESS_SET: |
|
3454 |
raise errors.OpPrereqError("Invalid disk access mode '%s'" % |
|
3455 |
mode) |
|
3456 |
size = disk.get("size", None) |
|
3457 |
if size is None: |
|
3458 |
raise errors.OpPrereqError("Missing disk size") |
|
3459 |
try: |
|
3460 |
size = int(size) |
|
3461 |
except ValueError: |
|
3462 |
raise errors.OpPrereqError("Invalid disk size '%s'" % size) |
|
3463 |
self.disks.append({"size": size, "mode": mode}) |
|
3464 |
|
|
3433 | 3465 |
# used in CheckPrereq for ip ping check |
3434 | 3466 |
self.check_ip = hostname1.ip |
3435 | 3467 |
|
3436 |
# MAC address verification |
|
3437 |
if self.op.mac not in (constants.VALUE_AUTO, constants.VALUE_GENERATE): |
|
3438 |
if not utils.IsValidMac(self.op.mac.lower()): |
|
3439 |
raise errors.OpPrereqError("invalid MAC address specified: %s" % |
|
3440 |
self.op.mac) |
|
3441 |
|
|
3442 | 3468 |
# file storage checks |
3443 | 3469 |
if (self.op.file_driver and |
3444 | 3470 |
not self.op.file_driver in constants.FILE_DRIVER): |
... | ... | |
3487 | 3513 |
"""Run the allocator based on input opcode. |
3488 | 3514 |
|
3489 | 3515 |
""" |
3490 |
disks = [{"size": self.op.disk_size, "mode": "w"}, |
|
3491 |
{"size": self.op.swap_size, "mode": "w"}] |
|
3492 |
nics = [{"mac": self.op.mac, "ip": getattr(self.op, "ip", None), |
|
3493 |
"bridge": self.op.bridge}] |
|
3516 |
nics = [n.ToDict() for n in self.nics] |
|
3494 | 3517 |
ial = IAllocator(self, |
3495 | 3518 |
mode=constants.IALLOCATOR_MODE_ALLOC, |
3496 | 3519 |
name=self.op.instance_name, |
... | ... | |
3499 | 3522 |
os=self.op.os_type, |
3500 | 3523 |
vcpus=self.be_full[constants.BE_VCPUS], |
3501 | 3524 |
mem_size=self.be_full[constants.BE_MEMORY], |
3502 |
disks=disks, |
|
3525 |
disks=self.disks,
|
|
3503 | 3526 |
nics=nics, |
3504 | 3527 |
) |
3505 | 3528 |
|
... | ... | |
3529 | 3552 |
""" |
3530 | 3553 |
env = { |
3531 | 3554 |
"INSTANCE_DISK_TEMPLATE": self.op.disk_template, |
3532 |
"INSTANCE_DISK_SIZE": self.op.disk_size, |
|
3533 |
"INSTANCE_SWAP_SIZE": self.op.swap_size, |
|
3555 |
"INSTANCE_DISK_SIZE": ",".join(str(d["size"]) for d in self.disks), |
|
3534 | 3556 |
"INSTANCE_ADD_MODE": self.op.mode, |
3535 | 3557 |
} |
3536 | 3558 |
if self.op.mode == constants.INSTANCE_IMPORT: |
... | ... | |
3545 | 3567 |
os_type=self.op.os_type, |
3546 | 3568 |
memory=self.be_full[constants.BE_MEMORY], |
3547 | 3569 |
vcpus=self.be_full[constants.BE_VCPUS], |
3548 |
nics=[(self.inst_ip, self.op.bridge, self.op.mac)],
|
|
3570 |
nics=[(n.ip, n.bridge, n.mac) for n in self.nics],
|
|
3549 | 3571 |
)) |
3550 | 3572 |
|
3551 | 3573 |
nl = ([self.cfg.GetMasterNode(), self.op.pnode] + |
... | ... | |
3581 | 3603 |
(ei_version, constants.EXPORT_VERSION)) |
3582 | 3604 |
|
3583 | 3605 |
# Check that the new instance doesn't have less disks than the export |
3584 |
# TODO: substitute "2" with the actual number of disks requested |
|
3585 |
instance_disks = 2 |
|
3606 |
instance_disks = len(self.disks) |
|
3586 | 3607 |
export_disks = export_info.getint(constants.INISECT_INS, 'disk_count') |
3587 | 3608 |
if instance_disks < export_disks: |
3588 | 3609 |
raise errors.OpPrereqError("Not enough disks to import." |
... | ... | |
3622 | 3643 |
raise errors.OpPrereqError("IP %s of instance %s already in use" % |
3623 | 3644 |
(self.check_ip, self.op.instance_name)) |
3624 | 3645 |
|
3625 |
# bridge verification |
|
3626 |
bridge = getattr(self.op, "bridge", None) |
|
3627 |
if bridge is None: |
|
3628 |
self.op.bridge = self.cfg.GetDefBridge() |
|
3629 |
else: |
|
3630 |
self.op.bridge = bridge |
|
3631 |
|
|
3632 | 3646 |
#### allocator run |
3633 | 3647 |
|
3634 | 3648 |
if self.op.iallocator is not None: |
... | ... | |
3655 | 3669 |
nodenames = [pnode.name] + self.secondaries |
3656 | 3670 |
|
3657 | 3671 |
req_size = _ComputeDiskSize(self.op.disk_template, |
3658 |
self.op.disk_size, self.op.swap_size)
|
|
3672 |
self.disks)
|
|
3659 | 3673 |
|
3660 | 3674 |
# Check lv size requirements |
3661 | 3675 |
if req_size is not None: |
... | ... | |
3684 | 3698 |
" primary node" % self.op.os_type) |
3685 | 3699 |
|
3686 | 3700 |
# bridge check on primary node |
3687 |
if not self.rpc.call_bridges_exist(self.pnode.name, [self.op.bridge]): |
|
3688 |
raise errors.OpPrereqError("target bridge '%s' does not exist on" |
|
3701 |
bridges = [n.bridge for n in self.nics] |
|
3702 |
if not self.rpc.call_bridges_exist(self.pnode.name, bridges): |
|
3703 |
raise errors.OpPrereqError("one of the target bridges '%s' does not" |
|
3704 |
" exist on" |
|
3689 | 3705 |
" destination node '%s'" % |
3690 |
(self.op.bridge, pnode.name))
|
|
3706 |
(",".join(bridges), pnode.name))
|
|
3691 | 3707 |
|
3692 | 3708 |
# memory check on primary node |
3693 | 3709 |
if self.op.start: |
... | ... | |
3708 | 3724 |
instance = self.op.instance_name |
3709 | 3725 |
pnode_name = self.pnode.name |
3710 | 3726 |
|
3711 |
if self.op.mac in (constants.VALUE_AUTO, constants.VALUE_GENERATE): |
|
3712 |
mac_address = self.cfg.GenerateMAC() |
|
3713 |
else: |
|
3714 |
mac_address = self.op.mac |
|
3715 |
|
|
3716 |
nic = objects.NIC(bridge=self.op.bridge, mac=mac_address) |
|
3717 |
if self.inst_ip is not None: |
|
3718 |
nic.ip = self.inst_ip |
|
3727 |
for nic in self.nics: |
|
3728 |
if nic.mac in (constants.VALUE_AUTO, constants.VALUE_GENERATE): |
|
3729 |
nic.mac = self.cfg.GenerateMAC() |
|
3719 | 3730 |
|
3720 | 3731 |
ht_kind = self.op.hypervisor |
3721 | 3732 |
if ht_kind in constants.HTS_REQ_PORT: |
... | ... | |
3741 | 3752 |
disks = _GenerateDiskTemplate(self, |
3742 | 3753 |
self.op.disk_template, |
3743 | 3754 |
instance, pnode_name, |
3744 |
self.secondaries, self.op.disk_size,
|
|
3745 |
self.op.swap_size,
|
|
3755 |
self.secondaries, |
|
3756 |
self.disks,
|
|
3746 | 3757 |
file_storage_dir, |
3747 | 3758 |
self.op.file_driver) |
3748 | 3759 |
|
3749 | 3760 |
iobj = objects.Instance(name=instance, os=self.op.os_type, |
3750 | 3761 |
primary_node=pnode_name, |
3751 |
nics=[nic], disks=disks,
|
|
3762 |
nics=self.nics, disks=disks,
|
|
3752 | 3763 |
disk_template=self.op.disk_template, |
3753 | 3764 |
status=self.instance_status, |
3754 | 3765 |
network_port=network_port, |
Also available in: Unified diff