Revision 7baf741d lib/cmdlib.py
b/lib/cmdlib.py | ||
---|---|---|
3071 | 3071 |
_OP_REQP = ["instance_name", "mem_size", "disk_size", |
3072 | 3072 |
"disk_template", "swap_size", "mode", "start", "vcpus", |
3073 | 3073 |
"wait_for_sync", "ip_check", "mac"] |
3074 |
REQ_BGL = False |
|
3075 |
|
|
3076 |
def _ExpandNode(self, node): |
|
3077 |
"""Expands and checks one node name. |
|
3078 |
|
|
3079 |
""" |
|
3080 |
node_full = self.cfg.ExpandNodeName(node) |
|
3081 |
if node_full is None: |
|
3082 |
raise errors.OpPrereqError("Unknown node %s" % node) |
|
3083 |
return node_full |
|
3084 |
|
|
3085 |
def ExpandNames(self): |
|
3086 |
"""ExpandNames for CreateInstance. |
|
3087 |
|
|
3088 |
Figure out the right locks for instance creation. |
|
3089 |
|
|
3090 |
""" |
|
3091 |
self.needed_locks = {} |
|
3092 |
|
|
3093 |
# set optional parameters to none if they don't exist |
|
3094 |
for attr in ["kernel_path", "initrd_path", "pnode", "snode", |
|
3095 |
"iallocator", "hvm_boot_order", "hvm_acpi", "hvm_pae", |
|
3096 |
"hvm_cdrom_image_path", "hvm_nic_type", "hvm_disk_type", |
|
3097 |
"vnc_bind_address"]: |
|
3098 |
if not hasattr(self.op, attr): |
|
3099 |
setattr(self.op, attr, None) |
|
3100 |
|
|
3101 |
# verify creation mode |
|
3102 |
if self.op.mode not in (constants.INSTANCE_CREATE, |
|
3103 |
constants.INSTANCE_IMPORT): |
|
3104 |
raise errors.OpPrereqError("Invalid instance creation mode '%s'" % |
|
3105 |
self.op.mode) |
|
3106 |
# disk template and mirror node verification |
|
3107 |
if self.op.disk_template not in constants.DISK_TEMPLATES: |
|
3108 |
raise errors.OpPrereqError("Invalid disk template name") |
|
3109 |
|
|
3110 |
#### instance parameters check |
|
3111 |
|
|
3112 |
# instance name verification |
|
3113 |
hostname1 = utils.HostInfo(self.op.instance_name) |
|
3114 |
self.op.instance_name = instance_name = hostname1.name |
|
3115 |
|
|
3116 |
# this is just a preventive check, but someone might still add this |
|
3117 |
# instance in the meantime, and creation will fail at lock-add time |
|
3118 |
if instance_name in self.cfg.GetInstanceList(): |
|
3119 |
raise errors.OpPrereqError("Instance '%s' is already in the cluster" % |
|
3120 |
instance_name) |
|
3121 |
|
|
3122 |
self.add_locks[locking.LEVEL_INSTANCE] = instance_name |
|
3123 |
|
|
3124 |
# ip validity checks |
|
3125 |
ip = getattr(self.op, "ip", None) |
|
3126 |
if ip is None or ip.lower() == "none": |
|
3127 |
inst_ip = None |
|
3128 |
elif ip.lower() == "auto": |
|
3129 |
inst_ip = hostname1.ip |
|
3130 |
else: |
|
3131 |
if not utils.IsValidIP(ip): |
|
3132 |
raise errors.OpPrereqError("given IP address '%s' doesn't look" |
|
3133 |
" like a valid IP" % ip) |
|
3134 |
inst_ip = ip |
|
3135 |
self.inst_ip = self.op.ip = inst_ip |
|
3136 |
# used in CheckPrereq for ip ping check |
|
3137 |
self.check_ip = hostname1.ip |
|
3138 |
|
|
3139 |
# MAC address verification |
|
3140 |
if self.op.mac != "auto": |
|
3141 |
if not utils.IsValidMac(self.op.mac.lower()): |
|
3142 |
raise errors.OpPrereqError("invalid MAC address specified: %s" % |
|
3143 |
self.op.mac) |
|
3144 |
|
|
3145 |
# boot order verification |
|
3146 |
if self.op.hvm_boot_order is not None: |
|
3147 |
if len(self.op.hvm_boot_order.strip("acdn")) != 0: |
|
3148 |
raise errors.OpPrereqError("invalid boot order specified," |
|
3149 |
" must be one or more of [acdn]") |
|
3150 |
# file storage checks |
|
3151 |
if (self.op.file_driver and |
|
3152 |
not self.op.file_driver in constants.FILE_DRIVER): |
|
3153 |
raise errors.OpPrereqError("Invalid file driver name '%s'" % |
|
3154 |
self.op.file_driver) |
|
3155 |
|
|
3156 |
if self.op.file_storage_dir and os.path.isabs(self.op.file_storage_dir): |
|
3157 |
raise errors.OpPrereqError("File storage directory path not absolute") |
|
3158 |
|
|
3159 |
### Node/iallocator related checks |
|
3160 |
if [self.op.iallocator, self.op.pnode].count(None) != 1: |
|
3161 |
raise errors.OpPrereqError("One and only one of iallocator and primary" |
|
3162 |
" node must be given") |
|
3163 |
|
|
3164 |
if self.op.iallocator: |
|
3165 |
self.needed_locks[locking.LEVEL_NODE] = locking.ALL_SET |
|
3166 |
else: |
|
3167 |
self.op.pnode = self._ExpandNode(self.op.pnode) |
|
3168 |
nodelist = [self.op.pnode] |
|
3169 |
if self.op.snode is not None: |
|
3170 |
self.op.snode = self._ExpandNode(self.op.snode) |
|
3171 |
nodelist.append(self.op.snode) |
|
3172 |
self.needed_locks[locking.LEVEL_NODE] = nodelist |
|
3173 |
|
|
3174 |
# in case of import lock the source node too |
|
3175 |
if self.op.mode == constants.INSTANCE_IMPORT: |
|
3176 |
src_node = getattr(self.op, "src_node", None) |
|
3177 |
src_path = getattr(self.op, "src_path", None) |
|
3178 |
|
|
3179 |
if src_node is None or src_path is None: |
|
3180 |
raise errors.OpPrereqError("Importing an instance requires source" |
|
3181 |
" node and path options") |
|
3182 |
|
|
3183 |
if not os.path.isabs(src_path): |
|
3184 |
raise errors.OpPrereqError("The source path must be absolute") |
|
3185 |
|
|
3186 |
self.op.src_node = src_node = self._ExpandNode(src_node) |
|
3187 |
if self.needed_locks[locking.LEVEL_NODE] is not locking.ALL_SET: |
|
3188 |
self.needed_locks[locking.LEVEL_NODE].append(src_node) |
|
3189 |
|
|
3190 |
else: # INSTANCE_CREATE |
|
3191 |
if getattr(self.op, "os_type", None) is None: |
|
3192 |
raise errors.OpPrereqError("No guest OS specified") |
|
3074 | 3193 |
|
3075 | 3194 |
def _RunAllocator(self): |
3076 | 3195 |
"""Run the allocator based on input opcode. |
... | ... | |
3146 | 3265 |
"""Check prerequisites. |
3147 | 3266 |
|
3148 | 3267 |
""" |
3149 |
# set optional parameters to none if they don't exist |
|
3150 |
for attr in ["kernel_path", "initrd_path", "hvm_boot_order", "pnode", |
|
3151 |
"iallocator", "hvm_acpi", "hvm_pae", "hvm_cdrom_image_path", |
|
3152 |
"hvm_nic_type", "hvm_disk_type", "vnc_bind_address"]: |
|
3153 |
if not hasattr(self.op, attr): |
|
3154 |
setattr(self.op, attr, None) |
|
3155 |
|
|
3156 |
if self.op.mode not in (constants.INSTANCE_CREATE, |
|
3157 |
constants.INSTANCE_IMPORT): |
|
3158 |
raise errors.OpPrereqError("Invalid instance creation mode '%s'" % |
|
3159 |
self.op.mode) |
|
3160 |
|
|
3161 | 3268 |
if (not self.cfg.GetVGName() and |
3162 | 3269 |
self.op.disk_template not in constants.DTS_NOT_LVM): |
3163 | 3270 |
raise errors.OpPrereqError("Cluster does not support lvm-based" |
3164 | 3271 |
" instances") |
3165 | 3272 |
|
3166 | 3273 |
if self.op.mode == constants.INSTANCE_IMPORT: |
3167 |
src_node = getattr(self.op, "src_node", None) |
|
3168 |
src_path = getattr(self.op, "src_path", None) |
|
3169 |
if src_node is None or src_path is None: |
|
3170 |
raise errors.OpPrereqError("Importing an instance requires source" |
|
3171 |
" node and path options") |
|
3172 |
src_node_full = self.cfg.ExpandNodeName(src_node) |
|
3173 |
if src_node_full is None: |
|
3174 |
raise errors.OpPrereqError("Unknown source node '%s'" % src_node) |
|
3175 |
self.op.src_node = src_node = src_node_full |
|
3176 |
|
|
3177 |
if not os.path.isabs(src_path): |
|
3178 |
raise errors.OpPrereqError("The source path must be absolute") |
|
3274 |
src_node = self.op.src_node |
|
3275 |
src_path = self.op.src_path |
|
3179 | 3276 |
|
3180 | 3277 |
export_info = rpc.call_export_info(src_node, src_path) |
3181 | 3278 |
|
... | ... | |
3199 | 3296 |
diskimage = os.path.join(src_path, export_info.get(constants.INISECT_INS, |
3200 | 3297 |
'disk0_dump')) |
3201 | 3298 |
self.src_image = diskimage |
3202 |
else: # INSTANCE_CREATE |
|
3203 |
if getattr(self.op, "os_type", None) is None: |
|
3204 |
raise errors.OpPrereqError("No guest OS specified") |
|
3205 |
|
|
3206 |
#### instance parameters check |
|
3207 |
|
|
3208 |
# disk template and mirror node verification |
|
3209 |
if self.op.disk_template not in constants.DISK_TEMPLATES: |
|
3210 |
raise errors.OpPrereqError("Invalid disk template name") |
|
3211 |
|
|
3212 |
# instance name verification |
|
3213 |
hostname1 = utils.HostInfo(self.op.instance_name) |
|
3214 |
|
|
3215 |
self.op.instance_name = instance_name = hostname1.name |
|
3216 |
instance_list = self.cfg.GetInstanceList() |
|
3217 |
if instance_name in instance_list: |
|
3218 |
raise errors.OpPrereqError("Instance '%s' is already in the cluster" % |
|
3219 |
instance_name) |
|
3220 | 3299 |
|
3221 |
# ip validity checks |
|
3222 |
ip = getattr(self.op, "ip", None) |
|
3223 |
if ip is None or ip.lower() == "none": |
|
3224 |
inst_ip = None |
|
3225 |
elif ip.lower() == "auto": |
|
3226 |
inst_ip = hostname1.ip |
|
3227 |
else: |
|
3228 |
if not utils.IsValidIP(ip): |
|
3229 |
raise errors.OpPrereqError("given IP address '%s' doesn't look" |
|
3230 |
" like a valid IP" % ip) |
|
3231 |
inst_ip = ip |
|
3232 |
self.inst_ip = self.op.ip = inst_ip |
|
3300 |
# ip ping checks (we use the same ip that was resolved in ExpandNames) |
|
3233 | 3301 |
|
3234 | 3302 |
if self.op.start and not self.op.ip_check: |
3235 | 3303 |
raise errors.OpPrereqError("Cannot ignore IP address conflicts when" |
3236 | 3304 |
" adding an instance in start mode") |
3237 | 3305 |
|
3238 | 3306 |
if self.op.ip_check: |
3239 |
if utils.TcpPing(hostname1.ip, constants.DEFAULT_NODED_PORT):
|
|
3307 |
if utils.TcpPing(self.check_ip, constants.DEFAULT_NODED_PORT):
|
|
3240 | 3308 |
raise errors.OpPrereqError("IP %s of instance %s already in use" % |
3241 |
(hostname1.ip, instance_name)) |
|
3242 |
|
|
3243 |
# MAC address verification |
|
3244 |
if self.op.mac != "auto": |
|
3245 |
if not utils.IsValidMac(self.op.mac.lower()): |
|
3246 |
raise errors.OpPrereqError("invalid MAC address specified: %s" % |
|
3247 |
self.op.mac) |
|
3309 |
(self.check_ip, instance_name)) |
|
3248 | 3310 |
|
3249 | 3311 |
# bridge verification |
3250 | 3312 |
bridge = getattr(self.op, "bridge", None) |
... | ... | |
3253 | 3315 |
else: |
3254 | 3316 |
self.op.bridge = bridge |
3255 | 3317 |
|
3256 |
# boot order verification |
|
3257 |
if self.op.hvm_boot_order is not None: |
|
3258 |
if len(self.op.hvm_boot_order.strip("acdn")) != 0: |
|
3259 |
raise errors.OpPrereqError("invalid boot order specified," |
|
3260 |
" must be one or more of [acdn]") |
|
3261 |
# file storage checks |
|
3262 |
if (self.op.file_driver and |
|
3263 |
not self.op.file_driver in constants.FILE_DRIVER): |
|
3264 |
raise errors.OpPrereqError("Invalid file driver name '%s'" % |
|
3265 |
self.op.file_driver) |
|
3266 |
|
|
3267 |
if self.op.file_storage_dir and os.path.isabs(self.op.file_storage_dir): |
|
3268 |
raise errors.OpPrereqError("File storage directory not a relative" |
|
3269 |
" path") |
|
3270 | 3318 |
#### allocator run |
3271 | 3319 |
|
3272 |
if [self.op.iallocator, self.op.pnode].count(None) != 1: |
|
3273 |
raise errors.OpPrereqError("One and only one of iallocator and primary" |
|
3274 |
" node must be given") |
|
3275 |
|
|
3276 | 3320 |
if self.op.iallocator is not None: |
3277 | 3321 |
self._RunAllocator() |
3278 | 3322 |
|
3279 | 3323 |
#### node related checks |
3280 | 3324 |
|
3281 | 3325 |
# check primary node |
3282 |
pnode = self.cfg.GetNodeInfo(self.cfg.ExpandNodeName(self.op.pnode)) |
|
3283 |
if pnode is None: |
|
3284 |
raise errors.OpPrereqError("Primary node '%s' is unknown" % |
|
3285 |
self.op.pnode) |
|
3286 |
self.op.pnode = pnode.name |
|
3287 |
self.pnode = pnode |
|
3326 |
self.pnode = pnode = self.cfg.GetNodeInfo(self.op.pnode) |
|
3327 |
assert self.pnode is not None, \ |
|
3328 |
"Cannot retrieve locked node %s" % self.op.pnode |
|
3288 | 3329 |
self.secondaries = [] |
3289 | 3330 |
|
3290 | 3331 |
# mirror node verification |
3291 | 3332 |
if self.op.disk_template in constants.DTS_NET_MIRROR: |
3292 |
if getattr(self.op, "snode", None) is None:
|
|
3333 |
if self.op.snode is None:
|
|
3293 | 3334 |
raise errors.OpPrereqError("The networked disk templates need" |
3294 | 3335 |
" a mirror node") |
3295 |
|
|
3296 |
snode_name = self.cfg.ExpandNodeName(self.op.snode) |
|
3297 |
if snode_name is None: |
|
3298 |
raise errors.OpPrereqError("Unknown secondary node '%s'" % |
|
3299 |
self.op.snode) |
|
3300 |
elif snode_name == pnode.name: |
|
3336 |
if self.op.snode == pnode.name: |
|
3301 | 3337 |
raise errors.OpPrereqError("The secondary node cannot be" |
3302 | 3338 |
" the primary node.") |
3303 |
self.secondaries.append(snode_name)
|
|
3339 |
self.secondaries.append(self.op.snode)
|
|
3304 | 3340 |
|
3305 | 3341 |
req_size = _ComputeDiskSize(self.op.disk_template, |
3306 | 3342 |
self.op.disk_size, self.op.swap_size) |
... | ... | |
3332 | 3368 |
if self.op.kernel_path == constants.VALUE_NONE: |
3333 | 3369 |
raise errors.OpPrereqError("Can't set instance kernel to none") |
3334 | 3370 |
|
3335 |
|
|
3336 | 3371 |
# bridge check on primary node |
3337 | 3372 |
if not rpc.call_bridges_exist(self.pnode.name, [self.op.bridge]): |
3338 | 3373 |
raise errors.OpPrereqError("target bridge '%s' does not exist on" |
... | ... | |
3347 | 3382 |
|
3348 | 3383 |
# hvm_cdrom_image_path verification |
3349 | 3384 |
if self.op.hvm_cdrom_image_path is not None: |
3385 |
# FIXME (als): shouldn't these checks happen on the destination node? |
|
3350 | 3386 |
if not os.path.isabs(self.op.hvm_cdrom_image_path): |
3351 | 3387 |
raise errors.OpPrereqError("The path to the HVM CDROM image must" |
3352 | 3388 |
" be an absolute path or None, not %s" % |
... | ... | |
3450 | 3486 |
feedback_fn("adding instance %s to cluster config" % instance) |
3451 | 3487 |
|
3452 | 3488 |
self.cfg.AddInstance(iobj) |
3453 |
# Add the new instance to the Ganeti Lock Manager |
|
3454 |
self.context.glm.add(locking.LEVEL_INSTANCE, instance) |
|
3489 |
# Declare that we don't want to remove the instance lock anymore, as we've |
|
3490 |
# added the instance to the config |
|
3491 |
del self.remove_locks[locking.LEVEL_INSTANCE] |
|
3455 | 3492 |
|
3456 | 3493 |
if self.op.wait_for_sync: |
3457 | 3494 |
disk_abort = not _WaitForSync(self.cfg, iobj, self.proc) |
... | ... | |
3466 | 3503 |
if disk_abort: |
3467 | 3504 |
_RemoveDisks(iobj, self.cfg) |
3468 | 3505 |
self.cfg.RemoveInstance(iobj.name) |
3469 |
# Remove the new instance from the Ganeti Lock Manager
|
|
3470 |
self.context.glm.remove(locking.LEVEL_INSTANCE, iobj.name)
|
|
3506 |
# Make sure the instance lock gets removed
|
|
3507 |
self.remove_locks[locking.LEVEL_INSTANCE] = iobj.name
|
|
3471 | 3508 |
raise errors.OpExecError("There are some degraded disks for" |
3472 | 3509 |
" this instance") |
3473 | 3510 |
|
Also available in: Unified diff