Revision 4c6e8e1a

b/NEWS
79 79
New features
80 80
~~~~~~~~~~~~
81 81

  
82
- Hotplug support. Introduce new option --hotplug to gnt-instance modify
82
- Hotplug support. Introduce new option '--hotplug' to ``gnt-instance modify``
83 83
  so that disk and NIC modifications take effect without the need of actual
84
  reboot. This feature is currently supported only for KVM hypervisor with
85
  version greater than 1.0.
84
  reboot. There are a couple of constrains currently for this feature:
85

  
86
   - only KVM hypervisor (versions >= 1.0) supports it,
87
   - one can not (yet) hotplug a disk using userspace access mode for RBD
88
   - in case of a downgrade instances should suffer a reboot in order to
89
     be migratable (due to core change of runtime files)
86 90
- The :doc:`Remote API <rapi>` daemon now supports a command line flag
87 91
  to always require authentication, ``--require-authentication``. It can
88 92
  be specified in ``$sysconfdir/default/ganeti``.
b/lib/cli.py
1641 1641

  
1642 1642
HOTPLUG_OPT = cli_option("--hotplug", dest="hotplug",
1643 1643
                         action="store_true", default=False,
1644
                         help="Try to hotplug device")
1644
                         help="Hotplug supported devices (NICs and Disks)")
1645 1645

  
1646 1646
#: Options provided by all commands
1647 1647
COMMON_OPTS = [DEBUG_OPT, REASON_OPT]
b/lib/client/gnt_instance.py
1314 1314

  
1315 1315
  nics = _ConvertNicDiskModifications(opts.nics)
1316 1316
  for action, _, __ in nics:
1317
    if action == constants.DDM_MODIFY and opts.hotplug:
1317
    if action == constants.DDM_MODIFY and opts.hotplug and not opts.force:
1318 1318
      usertext = ("You are about to hot-modify a NIC. This will be done"
1319 1319
                  " by removing the exisiting and then adding a new one."
1320 1320
                  " Network connection might be lost. Continue?")
......
1363 1363
    ToStdout("Modified instance %s", args[0])
1364 1364
    for param, data in result:
1365 1365
      ToStdout(" - %-5s -> %s", param, data)
1366
    if not opts.hotplug:
1367
      ToStdout("Please don't forget that most parameters take effect"
1368
               " only at the next (re)start of the instance initiated by"
1369
               " ganeti; restarting from within the instance will"
1370
               " not be enough.")
1366
    ToStdout("Please don't forget that most parameters take effect"
1367
             " only at the next (re)start of the instance initiated by"
1368
             " ganeti; restarting from within the instance will"
1369
             " not be enough.")
1371 1370
  return 0
1372 1371

  
1373 1372

  
b/lib/cmdlib/instance.py
2190 2190
      if op == constants.DDM_REMOVE:
2191 2191
        assert not params
2192 2192

  
2193
        if remove_fn is not None:
2194
          remove_fn(absidx, item, private)
2195

  
2196 2193
        changes = [("%s/%s" % (kind, absidx), "remove")]
2197 2194

  
2195
        if remove_fn is not None:
2196
          msg = remove_fn(absidx, item, private)
2197
          if msg:
2198
            changes.append(("%s/%s" % (kind, absidx), msg))
2199

  
2198 2200
        assert container[absidx] == item
2199 2201
        del container[absidx]
2200 2202
      elif op == constants.DDM_MODIFY:
......
3155 3157

  
3156 3158
  def _HotplugDevice(self, action, dev_type, device, extra, seq):
3157 3159
    self.LogInfo("Trying to hotplug device...")
3160
    msg = "hotplug:"
3158 3161
    result = self.rpc.call_hotplug_device(self.instance.primary_node,
3159 3162
                                          self.instance, action, dev_type,
3160 3163
                                          (device, self.instance),
......
3162 3165
    if result.fail_msg:
3163 3166
      self.LogWarning("Could not hotplug device: %s" % result.fail_msg)
3164 3167
      self.LogInfo("Continuing execution..")
3168
      msg += "failed"
3165 3169
    else:
3166 3170
      self.LogInfo("Hotplug done.")
3171
      msg += "done"
3172
    return msg
3167 3173

  
3168 3174
  def _CreateNewDisk(self, idx, params, _):
3169 3175
    """Creates a new disk.
......
3192 3198
                         disks=[(idx, disk, 0)],
3193 3199
                         cleanup=new_disks)
3194 3200

  
3201
    changes = [
3202
      ("disk/%d" % idx,
3203
      "add:size=%s,mode=%s" % (disk.size, disk.mode)),
3204
      ]
3195 3205
    if self.op.hotplug:
3196 3206
      self.cfg.SetDiskID(disk, self.instance.primary_node)
3197 3207
      result = self.rpc.call_blockdev_assemble(self.instance.primary_node,
3198 3208
                                               (disk, self.instance),
3199 3209
                                               self.instance.name, True, idx)
3200 3210
      if result.fail_msg:
3211
        changes.append(("disk/%d" % idx, "assemble:failed"))
3201 3212
        self.LogWarning("Can't assemble newly created disk %d: %s",
3202 3213
                        idx, result.fail_msg)
3203 3214
      else:
3204 3215
        _, link_name = result.payload
3205
        self._HotplugDevice(constants.HOTPLUG_ACTION_ADD,
3206
                            constants.HOTPLUG_TARGET_DISK,
3207
                            disk, link_name, idx)
3216
        msg = self._HotplugDevice(constants.HOTPLUG_ACTION_ADD,
3217
                                  constants.HOTPLUG_TARGET_DISK,
3218
                                  disk, link_name, idx)
3219
        changes.append(("disk/%d" % idx, msg))
3208 3220

  
3209
    return (disk, [
3210
      ("disk/%d" % idx, "add:size=%s,mode=%s" % (disk.size, disk.mode)),
3211
      ])
3221
    return (disk, changes)
3212 3222

  
3213 3223
  def _ModifyDisk(self, idx, disk, params, _):
3214 3224
    """Modifies a disk.
......
3243 3253
    """Removes a disk.
3244 3254

  
3245 3255
    """
3256
    hotmsg = ""
3246 3257
    if self.op.hotplug:
3247
      self._HotplugDevice(constants.HOTPLUG_ACTION_REMOVE,
3248
                          constants.HOTPLUG_TARGET_DISK,
3249
                          root, None, idx)
3258
      hotmsg = self._HotplugDevice(constants.HOTPLUG_ACTION_REMOVE,
3259
                                   constants.HOTPLUG_TARGET_DISK,
3260
                                   root, None, idx)
3250 3261
      ShutdownInstanceDisks(self, self.instance, [root])
3251 3262

  
3252 3263
    (anno_disk,) = AnnotateDiskParams(self.instance, [root], self.cfg)
......
3261 3272
    if root.dev_type in constants.LDS_DRBD:
3262 3273
      self.cfg.AddTcpUdpPort(root.logical_id[2])
3263 3274

  
3275
    return hotmsg
3276

  
3264 3277
  def _CreateNewNic(self, idx, params, private):
3265 3278
    """Creates data structure for a new network interface.
3266 3279

  
......
3276 3289
                       nicparams=nicparams)
3277 3290
    nobj.uuid = self.cfg.GenerateUniqueID(self.proc.GetECId())
3278 3291

  
3279
    if self.op.hotplug:
3280
      self._HotplugDevice(constants.HOTPLUG_ACTION_ADD,
3281
                          constants.HOTPLUG_TARGET_NIC,
3282
                          nobj, None, idx)
3283

  
3284
    desc = [
3292
    changes = [
3285 3293
      ("nic.%d" % idx,
3286 3294
       "add:mac=%s,ip=%s,mode=%s,link=%s,network=%s" %
3287 3295
       (mac, ip, private.filled[constants.NIC_MODE],
3288 3296
       private.filled[constants.NIC_LINK], net)),
3289 3297
      ]
3290 3298

  
3291
    return (nobj, desc)
3299
    if self.op.hotplug:
3300
      msg = self._HotplugDevice(constants.HOTPLUG_ACTION_ADD,
3301
                                constants.HOTPLUG_TARGET_NIC,
3302
                                nobj, None, idx)
3303
      changes.append(("nic.%d" % idx, msg))
3304

  
3305
    return (nobj, changes)
3292 3306

  
3293 3307
  def _ApplyNicMods(self, idx, nic, params, private):
3294 3308
    """Modifies a network interface.
......
3314 3328
        changes.append(("nic.%s/%d" % (key, idx), val))
3315 3329

  
3316 3330
    if self.op.hotplug:
3317
      self._HotplugDevice(constants.HOTPLUG_ACTION_MODIFY,
3318
                          constants.HOTPLUG_TARGET_NIC,
3319
                          nic, None, idx)
3331
      msg = self._HotplugDevice(constants.HOTPLUG_ACTION_MODIFY,
3332
                                constants.HOTPLUG_TARGET_NIC,
3333
                                nic, None, idx)
3334
      changes.append(("nic/%d" % idx, msg))
3320 3335

  
3321 3336
    return changes
3322 3337

  
3323 3338
  def _RemoveNic(self, idx, nic, _):
3324 3339
    if self.op.hotplug:
3325
      self._HotplugDevice(constants.HOTPLUG_ACTION_REMOVE,
3326
                          constants.HOTPLUG_TARGET_NIC,
3327
                          nic, None, idx)
3340
      return self._HotplugDevice(constants.HOTPLUG_ACTION_REMOVE,
3341
                                 constants.HOTPLUG_TARGET_NIC,
3342
                                 nic, None, idx)
3328 3343

  
3329 3344
  def Exec(self, feedback_fn):
3330 3345
    """Modifies an instance.
b/man/gnt-instance.rst
1184 1184
If ``--ignore-ipolicy`` is given any instance policy violations occuring
1185 1185
during this operation are ignored.
1186 1186

  
1187
If ``--hotplug`` is given any disk and nic modifications will take
1187
If ``--hotplug`` is given any disk and NIC modifications will take
1188 1188
effect without the need of actual reboot. Please note that this feature
1189
is currently supported only for KVM hypervisor and for versions greater
1190
than 1.0.
1189
is currently supported only for KVM hypervisor and there are some
1190
restrictions: a) KVM versions >= 1.0 support it b) instances with chroot
1191
or uid pool security model do not support disk hotplug c) RBD disks with
1192
userspace access mode can not be hotplugged (yet) d) if hotplug fails
1193
(for any reason) a warning is printed but execution is continued e)
1194
for existing NIC modification interactive verification is needed unless
1195
``--force`` option is passed.
1191 1196

  
1192 1197
See **ganeti**\(7) for a description of ``--submit`` and other common
1193 1198
options.
b/qa/qa_instance.py
684 684
    qa_config.TestEnabled("instance-device-hotplug"):
685 685
    args.extend([
686 686
      ["--net", "-1:add", "--hotplug"],
687
      ["--net", "-1:modify,mac=aa:bb:cc:dd:ee:ff", "--hotplug"],
687
      ["--net", "-1:modify,mac=aa:bb:cc:dd:ee:ff", "--hotplug", "--force"],
688 688
      ["--net", "-1:remove", "--hotplug"],
689 689
      ["--disk", "-1:add,size=1G", "--hotplug"],
690 690
      ["--disk", "-1:remove", "--hotplug"],

Also available in: Unified diff