7733 |
7733 |
self.op.beparams = {}
|
7734 |
7734 |
if not hasattr(self.op, 'hvparams'):
|
7735 |
7735 |
self.op.hvparams = {}
|
|
7736 |
if not hasattr(self.op, "disk_template"):
|
|
7737 |
self.op.disk_template = None
|
|
7738 |
if not hasattr(self.op, "remote_node"):
|
|
7739 |
self.op.remote_node = None
|
7736 |
7740 |
self.op.force = getattr(self.op, "force", False)
|
7737 |
|
if not (self.op.nics or self.op.disks or
|
|
7741 |
if not (self.op.nics or self.op.disks or self.op.disk_template or
|
7738 |
7742 |
self.op.hvparams or self.op.beparams):
|
7739 |
7743 |
raise errors.OpPrereqError("No changes submitted", errors.ECODE_INVAL)
|
7740 |
7744 |
|
... | ... | |
7781 |
7785 |
raise errors.OpPrereqError("Only one disk add or remove operation"
|
7782 |
7786 |
" supported at a time", errors.ECODE_INVAL)
|
7783 |
7787 |
|
|
7788 |
if self.op.disks and self.op.disk_template is not None:
|
|
7789 |
raise errors.OpPrereqError("Disk template conversion and other disk"
|
|
7790 |
" changes not supported at the same time",
|
|
7791 |
errors.ECODE_INVAL)
|
|
7792 |
|
|
7793 |
if self.op.disk_template:
|
|
7794 |
_CheckDiskTemplate(self.op.disk_template)
|
|
7795 |
if (self.op.disk_template in constants.DTS_NET_MIRROR and
|
|
7796 |
self.op.remote_node is None):
|
|
7797 |
raise errors.OpPrereqError("Changing the disk template to a mirrored"
|
|
7798 |
" one requires specifying a secondary node",
|
|
7799 |
errors.ECODE_INVAL)
|
|
7800 |
|
7784 |
7801 |
# NIC validation
|
7785 |
7802 |
nic_addremove = 0
|
7786 |
7803 |
for nic_op, nic_dict in self.op.nics:
|
... | ... | |
7843 |
7860 |
def DeclareLocks(self, level):
|
7844 |
7861 |
if level == locking.LEVEL_NODE:
|
7845 |
7862 |
self._LockInstancesNodes()
|
|
7863 |
if self.op.disk_template and self.op.remote_node:
|
|
7864 |
self.op.remote_node = _ExpandNodeName(self.cfg, self.op.remote_node)
|
|
7865 |
self.needed_locks[locking.LEVEL_NODE].append(self.op.remote_node)
|
7846 |
7866 |
|
7847 |
7867 |
def BuildHooksEnv(self):
|
7848 |
7868 |
"""Build hooks env.
|
... | ... | |
7892 |
7912 |
del args['nics'][-1]
|
7893 |
7913 |
|
7894 |
7914 |
env = _BuildInstanceHookEnvByObject(self, self.instance, override=args)
|
|
7915 |
if self.op.disk_template:
|
|
7916 |
env["NEW_DISK_TEMPLATE"] = self.op.disk_template
|
7895 |
7917 |
nl = [self.cfg.GetMasterNode()] + list(self.instance.all_nodes)
|
7896 |
7918 |
return env, nl, nl
|
7897 |
7919 |
|
... | ... | |
7945 |
7967 |
pnode = instance.primary_node
|
7946 |
7968 |
nodelist = list(instance.all_nodes)
|
7947 |
7969 |
|
|
7970 |
if self.op.disk_template:
|
|
7971 |
if instance.disk_template == self.op.disk_template:
|
|
7972 |
raise errors.OpPrereqError("Instance already has disk template %s" %
|
|
7973 |
instance.disk_template, errors.ECODE_INVAL)
|
|
7974 |
|
|
7975 |
if (instance.disk_template,
|
|
7976 |
self.op.disk_template) not in self._DISK_CONVERSIONS:
|
|
7977 |
raise errors.OpPrereqError("Unsupported disk template conversion from"
|
|
7978 |
" %s to %s" % (instance.disk_template,
|
|
7979 |
self.op.disk_template),
|
|
7980 |
errors.ECODE_INVAL)
|
|
7981 |
if self.op.disk_template in constants.DTS_NET_MIRROR:
|
|
7982 |
_CheckNodeOnline(self, self.op.remote_node)
|
|
7983 |
_CheckNodeNotDrained(self, self.op.remote_node)
|
|
7984 |
disks = [{"size": d.size} for d in instance.disks]
|
|
7985 |
required = _ComputeDiskSize(self.op.disk_template, disks)
|
|
7986 |
_CheckNodesFreeDisk(self, [self.op.remote_node], required)
|
|
7987 |
_CheckInstanceDown(self, instance, "cannot change disk template")
|
|
7988 |
|
7948 |
7989 |
# hvparams processing
|
7949 |
7990 |
if self.op.hvparams:
|
7950 |
7991 |
i_hvdict, hv_new = self._GetUpdatedParams(
|
... | ... | |
8128 |
8169 |
|
8129 |
8170 |
return
|
8130 |
8171 |
|
|
8172 |
def _ConvertPlainToDrbd(self, feedback_fn):
|
|
8173 |
"""Converts an instance from plain to drbd.
|
|
8174 |
|
|
8175 |
"""
|
|
8176 |
feedback_fn("Converting template to drbd")
|
|
8177 |
instance = self.instance
|
|
8178 |
pnode = instance.primary_node
|
|
8179 |
snode = self.op.remote_node
|
|
8180 |
|
|
8181 |
# create a fake disk info for _GenerateDiskTemplate
|
|
8182 |
disk_info = [{"size": d.size, "mode": d.mode} for d in instance.disks]
|
|
8183 |
new_disks = _GenerateDiskTemplate(self, self.op.disk_template,
|
|
8184 |
instance.name, pnode, [snode],
|
|
8185 |
disk_info, None, None, 0)
|
|
8186 |
info = _GetInstanceInfoText(instance)
|
|
8187 |
feedback_fn("Creating aditional volumes...")
|
|
8188 |
# first, create the missing data and meta devices
|
|
8189 |
for disk in new_disks:
|
|
8190 |
# unfortunately this is... not too nice
|
|
8191 |
_CreateSingleBlockDev(self, pnode, instance, disk.children[1],
|
|
8192 |
info, True)
|
|
8193 |
for child in disk.children:
|
|
8194 |
_CreateSingleBlockDev(self, snode, instance, child, info, True)
|
|
8195 |
# at this stage, all new LVs have been created, we can rename the
|
|
8196 |
# old ones
|
|
8197 |
feedback_fn("Renaming original volumes...")
|
|
8198 |
rename_list = [(o, n.children[0].logical_id)
|
|
8199 |
for (o, n) in zip(instance.disks, new_disks)]
|
|
8200 |
result = self.rpc.call_blockdev_rename(pnode, rename_list)
|
|
8201 |
result.Raise("Failed to rename original LVs")
|
|
8202 |
|
|
8203 |
feedback_fn("Initializing DRBD devices...")
|
|
8204 |
# all child devices are in place, we can now create the DRBD devices
|
|
8205 |
for disk in new_disks:
|
|
8206 |
for node in [pnode, snode]:
|
|
8207 |
f_create = node == pnode
|
|
8208 |
_CreateSingleBlockDev(self, node, instance, disk, info, f_create)
|
|
8209 |
|
|
8210 |
# at this point, the instance has been modified
|
|
8211 |
instance.disk_template = constants.DT_DRBD8
|
|
8212 |
instance.disks = new_disks
|
|
8213 |
self.cfg.Update(instance, feedback_fn)
|
|
8214 |
|
|
8215 |
# disks are created, waiting for sync
|
|
8216 |
disk_abort = not _WaitForSync(self, instance)
|
|
8217 |
if disk_abort:
|
|
8218 |
raise errors.OpExecError("There are some degraded disks for"
|
|
8219 |
" this instance, please cleanup manually")
|
|
8220 |
|
8131 |
8221 |
def Exec(self, feedback_fn):
|
8132 |
8222 |
"""Modifies an instance.
|
8133 |
8223 |
|
... | ... | |
8192 |
8282 |
# change a given disk
|
8193 |
8283 |
instance.disks[disk_op].mode = disk_dict['mode']
|
8194 |
8284 |
result.append(("disk.mode/%d" % disk_op, disk_dict['mode']))
|
|
8285 |
|
|
8286 |
if self.op.disk_template:
|
|
8287 |
r_shut = _ShutdownInstanceDisks(self, instance)
|
|
8288 |
if not r_shut:
|
|
8289 |
raise errors.OpExecError("Cannot shutdow instance disks, unable to"
|
|
8290 |
" proceed with disk template conversion")
|
|
8291 |
mode = (instance.disk_template, self.op.disk_template)
|
|
8292 |
try:
|
|
8293 |
self._DISK_CONVERSIONS[mode](self, feedback_fn)
|
|
8294 |
except:
|
|
8295 |
self.cfg.ReleaseDRBDMinors(instance.name)
|
|
8296 |
raise
|
|
8297 |
result.append(("disk_template", self.op.disk_template))
|
|
8298 |
|
8195 |
8299 |
# NIC changes
|
8196 |
8300 |
for nic_op, nic_dict in self.op.nics:
|
8197 |
8301 |
if nic_op == constants.DDM_REMOVE:
|
... | ... | |
8236 |
8340 |
|
8237 |
8341 |
return result
|
8238 |
8342 |
|
|
8343 |
_DISK_CONVERSIONS = {
|
|
8344 |
(constants.DT_PLAIN, constants.DT_DRBD8): _ConvertPlainToDrbd,
|
|
8345 |
}
|
8239 |
8346 |
|
8240 |
8347 |
class LUQueryExports(NoHooksLU):
|
8241 |
8348 |
"""Query the exports list
|