Revision 74409b12 lib/cmdlib.py
b/lib/cmdlib.py | ||
---|---|---|
31 | 31 |
import re |
32 | 32 |
import platform |
33 | 33 |
import logging |
34 |
import copy |
|
34 | 35 |
|
35 | 36 |
from ganeti import ssh |
36 | 37 |
from ganeti import logger |
... | ... | |
3139 | 3140 |
return req_size_dict[disk_template] |
3140 | 3141 |
|
3141 | 3142 |
|
3143 |
def _CheckHVParams(lu, nodenames, hvname, hvparams): |
|
3144 |
"""Hypervisor parameter validation. |
|
3145 |
|
|
3146 |
This function abstract the hypervisor parameter validation to be |
|
3147 |
used in both instance create and instance modify. |
|
3148 |
|
|
3149 |
@type lu: L{LogicalUnit} |
|
3150 |
@param lu: the logical unit for which we check |
|
3151 |
@type nodenames: list |
|
3152 |
@param nodenames: the list of nodes on which we should check |
|
3153 |
@type hvname: string |
|
3154 |
@param hvname: the name of the hypervisor we should use |
|
3155 |
@type hvparams: dict |
|
3156 |
@param hvparams: the parameters which we need to check |
|
3157 |
@raise errors.OpPrereqError: if the parameters are not valid |
|
3158 |
|
|
3159 |
""" |
|
3160 |
hvinfo = lu.rpc.call_hypervisor_validate_params(nodenames, |
|
3161 |
hvname, |
|
3162 |
hvparams) |
|
3163 |
for node in nodenames: |
|
3164 |
info = hvinfo.get(node, None) |
|
3165 |
if not info or not isinstance(info, (tuple, list)): |
|
3166 |
raise errors.OpPrereqError("Cannot get current information" |
|
3167 |
" from node '%s' (%s)" % (node, info)) |
|
3168 |
if not info[0]: |
|
3169 |
raise errors.OpPrereqError("Hypervisor parameter validation failed:" |
|
3170 |
" %s" % info[1]) |
|
3171 |
|
|
3172 |
|
|
3142 | 3173 |
class LUCreateInstance(LogicalUnit): |
3143 | 3174 |
"""Create an instance. |
3144 | 3175 |
|
... | ... | |
3449 | 3480 |
" %d MB available, %d MB required" % |
3450 | 3481 |
(node, info['vg_free'], req_size)) |
3451 | 3482 |
|
3452 |
# hypervisor parameter validation |
|
3453 |
hvinfo = self.rpc.call_hypervisor_validate_params(nodenames, |
|
3454 |
self.op.hypervisor, |
|
3455 |
self.op.hvparams) |
|
3456 |
for node in nodenames: |
|
3457 |
info = hvinfo.get(node, None) |
|
3458 |
if not info or not isinstance(info, (tuple, list)): |
|
3459 |
raise errors.OpPrereqError("Cannot get current information" |
|
3460 |
" from node '%s' (%s)" % (node, info)) |
|
3461 |
if not info[0]: |
|
3462 |
raise errors.OpPrereqError("Hypervisor parameter validation failed:" |
|
3463 |
" %s" % info[1]) |
|
3483 |
_CheckHVParams(self, nodenames, self.op.hypervisor, self.op.hvparams) |
|
3464 | 3484 |
|
3465 | 3485 |
# os verification |
3466 | 3486 |
os_obj = self.rpc.call_os_get(pnode.name, self.op.os_type) |
... | ... | |
4450 | 4470 |
""" |
4451 | 4471 |
HPATH = "instance-modify" |
4452 | 4472 |
HTYPE = constants.HTYPE_INSTANCE |
4453 |
_OP_REQP = ["instance_name"] |
|
4473 |
_OP_REQP = ["instance_name", "hvparams"]
|
|
4454 | 4474 |
REQ_BGL = False |
4455 | 4475 |
|
4456 | 4476 |
def ExpandNames(self): |
4457 | 4477 |
self._ExpandAndLockInstance() |
4478 |
self.needed_locks[locking.LEVEL_NODE] = [] |
|
4479 |
self.recalculate_locks[locking.LEVEL_NODE] = constants.LOCKS_REPLACE |
|
4480 |
|
|
4481 |
|
|
4482 |
def DeclareLocks(self, level): |
|
4483 |
if level == locking.LEVEL_NODE: |
|
4484 |
self._LockInstancesNodes() |
|
4458 | 4485 |
|
4459 | 4486 |
def BuildHooksEnv(self): |
4460 | 4487 |
"""Build hooks env. |
... | ... | |
4502 | 4529 |
self.bridge = getattr(self.op, "bridge", None) |
4503 | 4530 |
self.kernel_path = getattr(self.op, "kernel_path", None) |
4504 | 4531 |
self.initrd_path = getattr(self.op, "initrd_path", None) |
4505 |
self.hvm_boot_order = getattr(self.op, "hvm_boot_order", None) |
|
4506 |
self.hvm_acpi = getattr(self.op, "hvm_acpi", None) |
|
4507 |
self.hvm_pae = getattr(self.op, "hvm_pae", None) |
|
4508 |
self.hvm_nic_type = getattr(self.op, "hvm_nic_type", None) |
|
4509 |
self.hvm_disk_type = getattr(self.op, "hvm_disk_type", None) |
|
4510 |
self.hvm_cdrom_image_path = getattr(self.op, "hvm_cdrom_image_path", None) |
|
4511 |
self.vnc_bind_address = getattr(self.op, "vnc_bind_address", None) |
|
4512 | 4532 |
self.force = getattr(self.op, "force", None) |
4513 |
all_parms = [self.mem, self.vcpus, self.ip, self.bridge, self.mac, |
|
4514 |
self.kernel_path, self.initrd_path, self.hvm_boot_order, |
|
4515 |
self.hvm_acpi, self.hvm_pae, self.hvm_cdrom_image_path, |
|
4516 |
self.vnc_bind_address, self.hvm_nic_type, self.hvm_disk_type] |
|
4517 |
if all_parms.count(None) == len(all_parms): |
|
4533 |
all_parms = [self.mem, self.vcpus, self.ip, self.bridge, self.mac] |
|
4534 |
if all_parms.count(None) == len(all_parms) and not self.op.hvparams: |
|
4518 | 4535 |
raise errors.OpPrereqError("No changes submitted") |
4519 | 4536 |
if self.mem is not None: |
4520 | 4537 |
try: |
... | ... | |
4543 | 4560 |
if not utils.IsValidMac(self.mac): |
4544 | 4561 |
raise errors.OpPrereqError('Invalid MAC address %s' % self.mac) |
4545 | 4562 |
|
4546 |
if self.kernel_path is not None: |
|
4547 |
self.do_kernel_path = True |
|
4548 |
if self.kernel_path == constants.VALUE_NONE: |
|
4549 |
raise errors.OpPrereqError("Can't set instance to no kernel") |
|
4550 |
|
|
4551 |
if self.kernel_path != constants.VALUE_DEFAULT: |
|
4552 |
if not os.path.isabs(self.kernel_path): |
|
4553 |
raise errors.OpPrereqError("The kernel path must be an absolute" |
|
4554 |
" filename") |
|
4555 |
else: |
|
4556 |
self.do_kernel_path = False |
|
4557 |
|
|
4558 |
if self.initrd_path is not None: |
|
4559 |
self.do_initrd_path = True |
|
4560 |
if self.initrd_path not in (constants.VALUE_NONE, |
|
4561 |
constants.VALUE_DEFAULT): |
|
4562 |
if not os.path.isabs(self.initrd_path): |
|
4563 |
raise errors.OpPrereqError("The initrd path must be an absolute" |
|
4564 |
" filename") |
|
4565 |
else: |
|
4566 |
self.do_initrd_path = False |
|
4567 |
|
|
4568 |
# boot order verification |
|
4569 |
if self.hvm_boot_order is not None: |
|
4570 |
if self.hvm_boot_order != constants.VALUE_DEFAULT: |
|
4571 |
if len(self.hvm_boot_order.strip("acdn")) != 0: |
|
4572 |
raise errors.OpPrereqError("invalid boot order specified," |
|
4573 |
" must be one or more of [acdn]" |
|
4574 |
" or 'default'") |
|
4575 |
|
|
4576 |
# hvm_cdrom_image_path verification |
|
4577 |
if self.op.hvm_cdrom_image_path is not None: |
|
4578 |
if not (os.path.isabs(self.op.hvm_cdrom_image_path) or |
|
4579 |
self.op.hvm_cdrom_image_path.lower() == "none"): |
|
4580 |
raise errors.OpPrereqError("The path to the HVM CDROM image must" |
|
4581 |
" be an absolute path or None, not %s" % |
|
4582 |
self.op.hvm_cdrom_image_path) |
|
4583 |
if not (os.path.isfile(self.op.hvm_cdrom_image_path) or |
|
4584 |
self.op.hvm_cdrom_image_path.lower() == "none"): |
|
4585 |
raise errors.OpPrereqError("The HVM CDROM image must either be a" |
|
4586 |
" regular file or a symlink pointing to" |
|
4587 |
" an existing regular file, not %s" % |
|
4588 |
self.op.hvm_cdrom_image_path) |
|
4589 |
|
|
4590 |
# vnc_bind_address verification |
|
4591 |
if self.op.vnc_bind_address is not None: |
|
4592 |
if not utils.IsValidIP(self.op.vnc_bind_address): |
|
4593 |
raise errors.OpPrereqError("given VNC bind address '%s' doesn't look" |
|
4594 |
" like a valid IP address" % |
|
4595 |
self.op.vnc_bind_address) |
|
4563 |
# checking the new params on the primary/secondary nodes |
|
4596 | 4564 |
|
4597 | 4565 |
instance = self.instance = self.cfg.GetInstanceInfo(self.op.instance_name) |
4598 | 4566 |
assert self.instance is not None, \ |
4599 | 4567 |
"Cannot retrieve locked instance %s" % self.op.instance_name |
4568 |
pnode = self.instance.primary_node |
|
4569 |
nodelist = [pnode] |
|
4570 |
nodelist.extend(instance.secondary_nodes) |
|
4571 |
|
|
4572 |
if self.op.hvparams: |
|
4573 |
i_hvdict = copy.deepcopy(instance.hvparams) |
|
4574 |
for key, val in self.op.hvparams.iteritems(): |
|
4575 |
if val is None: |
|
4576 |
try: |
|
4577 |
del i_hvdict[key] |
|
4578 |
except KeyError: |
|
4579 |
pass |
|
4580 |
else: |
|
4581 |
i_hvdict[key] = val |
|
4582 |
cluster = self.cfg.GetClusterInfo() |
|
4583 |
hv_new = cluster.FillDict(cluster.hvparams[instance.hypervisor], |
|
4584 |
i_hvdict) |
|
4585 |
# local check |
|
4586 |
hypervisor.GetHypervisor( |
|
4587 |
instance.hypervisor).CheckParameterSyntax(hv_new) |
|
4588 |
_CheckHVParams(self, nodelist, instance.hypervisor, hv_new) |
|
4589 |
self.hv_new = hv_new |
|
4590 |
|
|
4600 | 4591 |
self.warn = [] |
4601 | 4592 |
if self.mem is not None and not self.force: |
4602 |
pnode = self.instance.primary_node |
|
4603 |
nodelist = [pnode] |
|
4604 |
nodelist.extend(instance.secondary_nodes) |
|
4605 | 4593 |
instance_info = self.rpc.call_instance_info(pnode, instance.name, |
4606 | 4594 |
instance.hypervisor) |
4607 | 4595 |
nodeinfo = self.rpc.call_node_info(nodelist, self.cfg.GetVGName(), |
... | ... | |
4628 | 4616 |
if node not in nodeinfo or not isinstance(nodeinfo[node], dict): |
4629 | 4617 |
self.warn.append("Can't get info from secondary node %s" % node) |
4630 | 4618 |
elif self.mem > nodeinfo[node]['memory_free']: |
4631 |
self.warn.append("Not enough memory to failover instance to secondary" |
|
4632 |
" node %s" % node) |
|
4633 |
|
|
4634 |
# Xen HVM device type checks |
|
4635 |
if instance.hypervisor == constants.HT_XEN_HVM: |
|
4636 |
if self.op.hvm_nic_type is not None: |
|
4637 |
if self.op.hvm_nic_type not in constants.HT_HVM_VALID_NIC_TYPES: |
|
4638 |
raise errors.OpPrereqError("Invalid NIC type %s specified for Xen" |
|
4639 |
" HVM hypervisor" % self.op.hvm_nic_type) |
|
4640 |
if self.op.hvm_disk_type is not None: |
|
4641 |
if self.op.hvm_disk_type not in constants.HT_HVM_VALID_DISK_TYPES: |
|
4642 |
raise errors.OpPrereqError("Invalid disk type %s specified for Xen" |
|
4643 |
" HVM hypervisor" % self.op.hvm_disk_type) |
|
4619 |
self.warn.append("Not enough memory to failover instance to" |
|
4620 |
" secondary node %s" % node) |
|
4644 | 4621 |
|
4645 | 4622 |
return |
4646 | 4623 |
|
... | ... | |
4671 | 4648 |
if self.mac: |
4672 | 4649 |
instance.nics[0].mac = self.mac |
4673 | 4650 |
result.append(("mac", self.mac)) |
4674 |
if self.do_kernel_path: |
|
4675 |
instance.kernel_path = self.kernel_path |
|
4676 |
result.append(("kernel_path", self.kernel_path)) |
|
4677 |
if self.do_initrd_path: |
|
4678 |
instance.initrd_path = self.initrd_path |
|
4679 |
result.append(("initrd_path", self.initrd_path)) |
|
4680 |
if self.hvm_boot_order: |
|
4681 |
if self.hvm_boot_order == constants.VALUE_DEFAULT: |
|
4682 |
instance.hvm_boot_order = None |
|
4683 |
else: |
|
4684 |
instance.hvm_boot_order = self.hvm_boot_order |
|
4685 |
result.append(("hvm_boot_order", self.hvm_boot_order)) |
|
4686 |
if self.hvm_acpi is not None: |
|
4687 |
instance.hvm_acpi = self.hvm_acpi |
|
4688 |
result.append(("hvm_acpi", self.hvm_acpi)) |
|
4689 |
if self.hvm_pae is not None: |
|
4690 |
instance.hvm_pae = self.hvm_pae |
|
4691 |
result.append(("hvm_pae", self.hvm_pae)) |
|
4692 |
if self.hvm_nic_type is not None: |
|
4693 |
instance.hvm_nic_type = self.hvm_nic_type |
|
4694 |
result.append(("hvm_nic_type", self.hvm_nic_type)) |
|
4695 |
if self.hvm_disk_type is not None: |
|
4696 |
instance.hvm_disk_type = self.hvm_disk_type |
|
4697 |
result.append(("hvm_disk_type", self.hvm_disk_type)) |
|
4698 |
if self.hvm_cdrom_image_path: |
|
4699 |
if self.hvm_cdrom_image_path == constants.VALUE_NONE: |
|
4700 |
instance.hvm_cdrom_image_path = None |
|
4701 |
else: |
|
4702 |
instance.hvm_cdrom_image_path = self.hvm_cdrom_image_path |
|
4703 |
result.append(("hvm_cdrom_image_path", self.hvm_cdrom_image_path)) |
|
4704 |
if self.vnc_bind_address: |
|
4705 |
instance.vnc_bind_address = self.vnc_bind_address |
|
4706 |
result.append(("vnc_bind_address", self.vnc_bind_address)) |
|
4651 |
if self.op.hvparams: |
|
4652 |
instance.hvparams = self.hv_new |
|
4653 |
for key, val in self.op.hvparams.iteritems(): |
|
4654 |
result.append(("hv/%s" % key, val)) |
|
4707 | 4655 |
|
4708 | 4656 |
self.cfg.Update(instance) |
4709 | 4657 |
|
Also available in: Unified diff