Revision 7baf741d

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