Revision 07813a9e

b/daemons/ganeti-noded
400 400

  
401 401
    """
402 402
    instance = objects.Instance.FromDict(params[0])
403
    extra_args = params[1]
404
    return backend.StartInstance(instance, extra_args)
403
    return backend.StartInstance(instance)
405 404

  
406 405
  @staticmethod
407 406
  def perspective_migration_info(params):
......
445 444
    """
446 445
    instance = objects.Instance.FromDict(params[0])
447 446
    reboot_type = params[1]
448
    extra_args = params[2]
449
    return backend.InstanceReboot(instance, reboot_type, extra_args)
447
    return backend.InstanceReboot(instance, reboot_type)
450 448

  
451 449
  @staticmethod
452 450
  def perspective_instance_info(params):
b/daemons/ganeti-watcher
214 214
    """Encapsulates the start of an instance.
215 215

  
216 216
    """
217
    op = opcodes.OpStartupInstance(instance_name=self.name,
218
                                   force=False,
219
                                   extra_args=None)
217
    op = opcodes.OpStartupInstance(instance_name=self.name, force=False)
220 218
    cli.SubmitOpCode(op, cl=client)
221 219

  
222 220
  def ActivateDisks(self):
b/lib/backend.py
856 856
  return block_devices
857 857

  
858 858

  
859
def StartInstance(instance, extra_args):
859
def StartInstance(instance):
860 860
  """Start an instance.
861 861

  
862 862
  @type instance: L{objects.Instance}
......
873 873
  try:
874 874
    block_devices = _GatherAndLinkBlockDevs(instance)
875 875
    hyper = hypervisor.GetHypervisor(instance.hypervisor)
876
    hyper.StartInstance(instance, block_devices, extra_args)
876
    hyper.StartInstance(instance, block_devices)
877 877
  except errors.BlockDeviceError, err:
878 878
    logging.exception("Failed to start instance")
879 879
    return (False, "Block device error: %s" % str(err))
......
941 941
  return (True, "Instance has been shutdown successfully")
942 942

  
943 943

  
944
def InstanceReboot(instance, reboot_type, extra_args):
944
def InstanceReboot(instance, reboot_type):
945 945
  """Reboot an instance.
946 946

  
947 947
  @type instance: L{objects.Instance}
......
980 980
      stop_result = InstanceShutdown(instance)
981 981
      if not stop_result[0]:
982 982
        return stop_result
983
      return StartInstance(instance, extra_args)
983
      return StartInstance(instance)
984 984
    except errors.HypervisorError, err:
985 985
      msg = "Failed to hard reboot instance %s: %s" % (instance.name, err)
986 986
      logging.error(msg)
b/lib/cmdlib.py
2720 2720
    """
2721 2721
    instance = self.instance
2722 2722
    force = self.op.force
2723
    extra_args = getattr(self.op, "extra_args", "")
2724 2723

  
2725 2724
    self.cfg.MarkInstanceUp(instance.name)
2726 2725

  
......
2728 2727

  
2729 2728
    _StartInstanceDisks(self, instance, force)
2730 2729

  
2731
    result = self.rpc.call_instance_start(node_current, instance, extra_args)
2730
    result = self.rpc.call_instance_start(node_current, instance)
2732 2731
    msg = result.RemoteFailMsg()
2733 2732
    if msg:
2734 2733
      _ShutdownInstanceDisks(self, instance)
......
2789 2788
    instance = self.instance
2790 2789
    ignore_secondaries = self.op.ignore_secondaries
2791 2790
    reboot_type = self.op.reboot_type
2792
    extra_args = getattr(self.op, "extra_args", "")
2793 2791

  
2794 2792
    node_current = instance.primary_node
2795 2793

  
......
2798 2796
      for disk in instance.disks:
2799 2797
        self.cfg.SetDiskID(disk, node_current)
2800 2798
      result = self.rpc.call_instance_reboot(node_current, instance,
2801
                                             reboot_type, extra_args)
2799
                                             reboot_type)
2802 2800
      msg = result.RemoteFailMsg()
2803 2801
      if msg:
2804 2802
        raise errors.OpExecError("Could not reboot instance: %s" % msg)
......
2810 2808
                                 " full reboot: %s" % msg)
2811 2809
      _ShutdownInstanceDisks(self, instance)
2812 2810
      _StartInstanceDisks(self, instance, ignore_secondaries)
2813
      result = self.rpc.call_instance_start(node_current, instance, extra_args)
2811
      result = self.rpc.call_instance_start(node_current, instance)
2814 2812
      msg = result.RemoteFailMsg()
2815 2813
      if msg:
2816 2814
        _ShutdownInstanceDisks(self, instance)
......
3500 3498
        raise errors.OpExecError("Can't activate the instance's disks")
3501 3499

  
3502 3500
      feedback_fn("* starting the instance on the target node")
3503
      result = self.rpc.call_instance_start(target_node, instance, None)
3501
      result = self.rpc.call_instance_start(target_node, instance)
3504 3502
      msg = result.RemoteFailMsg()
3505 3503
      if msg:
3506 3504
        _ShutdownInstanceDisks(self, instance)
......
4741 4739
      self.cfg.Update(iobj)
4742 4740
      logging.info("Starting instance %s on node %s", instance, pnode_name)
4743 4741
      feedback_fn("* starting instance...")
4744
      result = self.rpc.call_instance_start(pnode_name, iobj, None)
4742
      result = self.rpc.call_instance_start(pnode_name, iobj)
4745 4743
      msg = result.RemoteFailMsg()
4746 4744
      if msg:
4747 4745
        raise errors.OpExecError("Could not start instance: %s" % msg)
......
6189 6187

  
6190 6188
    finally:
6191 6189
      if self.op.shutdown and instance.admin_up:
6192
        result = self.rpc.call_instance_start(src_node, instance, None)
6190
        result = self.rpc.call_instance_start(src_node, instance)
6193 6191
        msg = result.RemoteFailMsg()
6194 6192
        if msg:
6195 6193
          _ShutdownInstanceDisks(self, instance)
b/lib/hypervisor/hv_base.py
38 38
  def __init__(self):
39 39
    pass
40 40

  
41
  def StartInstance(self, instance, block_devices, extra_args):
41
  def StartInstance(self, instance, block_devices):
42 42
    """Start an instance."""
43 43
    raise NotImplementedError
44 44

  
b/lib/hypervisor/hv_fake.py
107 107
        raise errors.HypervisorError("Failed to list instances: %s" % err)
108 108
    return data
109 109

  
110
  def StartInstance(self, instance, block_devices, extra_args):
110
  def StartInstance(self, instance, block_devices):
111 111
    """Start an instance.
112 112

  
113 113
    For the fake hypervisor, it just creates a file in the base dir,
b/lib/hypervisor/hv_kvm.py
52 52
    constants.HV_KERNEL_PATH,
53 53
    constants.HV_INITRD_PATH,
54 54
    constants.HV_ROOT_PATH,
55
    constants.HV_KERNEL_ARGS,
55 56
    constants.HV_ACPI,
56 57
    constants.HV_SERIAL_CONSOLE,
57 58
    constants.HV_VNC_BIND_ADDRESS,
......
219 220

  
220 221
    return data
221 222

  
222
  def _GenerateKVMRuntime(self, instance, block_devices, extra_args):
223
  def _GenerateKVMRuntime(self, instance, block_devices):
223 224
    """Generate KVM information to start an instance.
224 225

  
225 226
    """
......
281 282
      initrd_path = hvp[constants.HV_INITRD_PATH]
282 283
      if initrd_path:
283 284
        kvm_cmd.extend(['-initrd', initrd_path])
284
      root_append = 'root=%s ro' % instance.hvparams[constants.HV_ROOT_PATH]
285
      if instance.hvparams[constants.HV_SERIAL_CONSOLE]:
286
        kvm_cmd.extend(['-append', 'console=ttyS0,38400 %s' % root_append])
287
      else:
288
        kvm_cmd.extend(['-append', root_append])
285
      root_append = ['root=%s' % hvp[constants.HV_ROOT_PATH],
286
                     hvp[constants.HV_KERNEL_ARGS]]
287
      if hvp[constants.HV_SERIAL_CONSOLE]:
288
        root_append.append('console=ttyS0,38400')
289
      kvm_cmd.extend(['-append', ' '.join(root_append)])
289 290

  
290 291
    mouse_type = hvp[constants.HV_USB_MOUSE]
291 292
    if mouse_type:
......
435 436
    for filename in temp_files:
436 437
      utils.RemoveFile(filename)
437 438

  
438
  def StartInstance(self, instance, block_devices, extra_args):
439
  def StartInstance(self, instance, block_devices):
439 440
    """Start an instance.
440 441

  
441 442
    """
......
444 445
      raise errors.HypervisorError("Failed to start instance %s: %s" %
445 446
                                   (instance.name, "already running"))
446 447

  
447
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices, extra_args)
448
    kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
448 449
    self._SaveKVMRuntime(instance, kvm_runtime)
449 450
    self._ExecuteKVMRuntime(instance, kvm_runtime)
450 451

  
b/lib/hypervisor/hv_xen.py
44 44
  """
45 45

  
46 46
  @classmethod
47
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
47
  def _WriteConfigFile(cls, instance, block_devices):
48 48
    """Write the Xen config file for the instance.
49 49

  
50 50
    """
......
159 159
    xm_list = self._GetXMList(False)
160 160
    return xm_list
161 161

  
162
  def StartInstance(self, instance, block_devices, extra_args):
162
  def StartInstance(self, instance, block_devices):
163 163
    """Start an instance.
164 164

  
165 165
    """
166
    self._WriteConfigFile(instance, block_devices, extra_args)
166
    self._WriteConfigFile(instance, block_devices)
167 167
    result = utils.RunCmd(["xm", "create", instance.name])
168 168

  
169 169
    if result.failed:
......
386 386
    constants.HV_KERNEL_PATH,
387 387
    constants.HV_INITRD_PATH,
388 388
    constants.HV_ROOT_PATH,
389
    constants.HV_KERNEL_ARGS,
389 390
    ]
390 391

  
391 392
  @classmethod
......
435 436
                                   " not a file" % initrd_path)
436 437

  
437 438
  @classmethod
438
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
439
  def _WriteConfigFile(cls, instance, block_devices):
439 440
    """Write the Xen config file for the instance.
440 441

  
441 442
    """
......
470 471
                 cls._GetConfigFileDiskData(instance.disk_template,
471 472
                                            block_devices)))
472 473

  
473
    rpath = instance.hvparams[constants.HV_ROOT_PATH]
474
    config.write("root = '%s ro'\n" % rpath)
474
    config.write("root = '%s'\n" % hvp[constants.HV_ROOT_PATH])
475 475
    config.write("on_poweroff = 'destroy'\n")
476 476
    config.write("on_reboot = 'restart'\n")
477 477
    config.write("on_crash = 'restart'\n")
478
    if extra_args:
479
      config.write("extra = '%s'\n" % extra_args)
478
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
480 479
    # just in case it exists
481 480
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
482 481
    try:
......
563 562
                                   iso_path)
564 563

  
565 564
  @classmethod
566
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
565
  def _WriteConfigFile(cls, instance, block_devices):
567 566
    """Create a Xen 3.1 HVM config file.
568 567

  
569 568
    """
......
654 653
    config.write("on_poweroff = 'destroy'\n")
655 654
    config.write("on_reboot = 'restart'\n")
656 655
    config.write("on_crash = 'restart'\n")
657
    if extra_args:
658
      config.write("extra = '%s'\n" % extra_args)
656
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
659 657
    # just in case it exists
660 658
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
661 659
    try:
b/lib/opcodes.py
382 382
  """Startup an instance."""
383 383
  OP_ID = "OP_INSTANCE_STARTUP"
384 384
  OP_DSC_FIELD = "instance_name"
385
  __slots__ = ["instance_name", "force", "extra_args"]
385
  __slots__ = ["instance_name", "force"]
386 386

  
387 387

  
388 388
class OpShutdownInstance(OpCode):
......
396 396
  """Reboot an instance."""
397 397
  OP_ID = "OP_INSTANCE_REBOOT"
398 398
  OP_DSC_FIELD = "instance_name"
399
  __slots__ = ["instance_name", "reboot_type", "extra_args",
400
               "ignore_secondaries" ]
399
  __slots__ = ["instance_name", "reboot_type", "ignore_secondaries" ]
401 400

  
402 401

  
403 402
class OpReplaceDisks(OpCode):
b/lib/rpc.py
425 425
    """
426 426
    return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
427 427

  
428
  def call_instance_start(self, node, instance, extra_args):
428
  def call_instance_start(self, node, instance):
429 429
    """Starts an instance.
430 430

  
431 431
    This is a single-node call.
432 432

  
433 433
    """
434 434
    return self._SingleNodeCall(node, "instance_start",
435
                                [self._InstDict(instance), extra_args])
435
                                [self._InstDict(instance)])
436 436

  
437 437
  def call_instance_shutdown(self, node, instance):
438 438
    """Stops an instance.
......
515 515
    return self._SingleNodeCall(node, "instance_migrate",
516 516
                                [self._InstDict(instance), target, live])
517 517

  
518
  def call_instance_reboot(self, node, instance, reboot_type, extra_args):
518
  def call_instance_reboot(self, node, instance, reboot_type):
519 519
    """Reboots an instance.
520 520

  
521 521
    This is a single-node call.
522 522

  
523 523
    """
524 524
    return self._SingleNodeCall(node, "instance_reboot",
525
                                [self._InstDict(instance), reboot_type,
526
                                 extra_args])
525
                                [self._InstDict(instance), reboot_type])
527 526

  
528 527
  def call_instance_os_add(self, node, inst):
529 528
    """Installs an OS on the given instance.
b/man/gnt-instance.sgml
428 428
            </varlistentry>
429 429

  
430 430
            <varlistentry>
431
              <term>kernel_args</term>
432
              <listitem>
433
                <simpara>Valid for the Xen PVM and KVM hypervisors.</simpara>
434

  
435
                <para>
436
                  This options specifies extra arguments to the kernel
437
                  that will be loaded.  device. This is always used
438
                  for Xen PVM, while for KVM it is only used if the
439
                  <option>kernel_path</option> option is also
440
                  specified.
441
                </para>
442

  
443
                <para>
444
                  The default setting for this value is simply
445
                  <constant>"ro"</constant>, which mounts the root
446
                  disk (initially) in read-only one. For example,
447
                  setting this to <userinput>single</userinput> will
448
                  cause the instance to start in single-user mode.
449
                </para>
450
              </listitem>
451
            </varlistentry>
452

  
453
            <varlistentry>
431 454
              <term>initrd_path</term>
432 455
              <listitem>
433 456
                <simpara>Valid for the Xen PVM and KVM hypervisors.</simpara>
......
1265 1288
        <cmdsynopsis>
1266 1289
          <command>startup</command>
1267 1290
          <sbr>
1268
          <arg>--extra=<replaceable>PARAMS</replaceable></arg>
1269 1291
          <arg>--force</arg>
1270 1292
          <sbr>
1271 1293
          <arg>--force-multiple</arg>
......
1336 1358
        </para>
1337 1359

  
1338 1360
        <para>
1339
          The <option>--extra</option> option is used to pass
1340
          additional argument to the instance's kernel for this start
1341
          only. Currently there is no way to specify a persistent set
1342
          of arguments (beside the one hardcoded). Note that this may
1343
          not apply to all virtualization types.
1344
        </para>
1345

  
1346
        <para>
1347 1361
          Use <option>--force</option> to start even if secondary disks are
1348 1362
          failing.
1349 1363
        </para>
......
1365 1379
          Example:
1366 1380
          <screen>
1367 1381
# gnt-instance start instance1.example.com
1368
# gnt-instance start --extra single test1.example.com
1369 1382
# gnt-instance start --node node1.example.com node2.example.com
1370 1383
# gnt-instance start --all
1371 1384
          </screen>
......
1432 1445
        <cmdsynopsis>
1433 1446
          <command>reboot</command>
1434 1447
          <sbr>
1435
          <arg>--extra=<replaceable>PARAMS</replaceable></arg>
1436
          <sbr>
1437 1448
          <arg>--type=<replaceable>REBOOT-TYPE</replaceable></arg>
1438 1449
          <sbr>
1439 1450
          <arg>--ignore-secondaries</arg>
b/scripts/gnt-instance
709 709
  jex = cli.JobExecutor(verbose=multi_on, cl=cl)
710 710
  for name in inames:
711 711
    op = opcodes.OpStartupInstance(instance_name=name,
712
                                   force=opts.force,
713
                                   extra_args=opts.extra_args)
712
                                   force=opts.force)
714 713
    jex.QueueJob(name, op)
715 714
  jex.WaitOrShow(not opts.submit_only)
716 715
  return 0
......
1457 1456
               "<instance>", "Stops an instance"),
1458 1457
  'startup': (StartupInstance, ARGS_ANY,
1459 1458
              [DEBUG_OPT, FORCE_OPT, m_force_multi,
1460
               make_option("-e", "--extra", dest="extra_args",
1461
                           help="Extra arguments for the instance's kernel",
1462
                           default=None, type="string", metavar="<PARAMS>"),
1463 1459
               m_node_opt, m_pri_node_opt, m_sec_node_opt,
1464 1460
               m_clust_opt, m_inst_opt,
1465 1461
               SUBMIT_OPT,
......
1468 1464

  
1469 1465
  'reboot': (RebootInstance, ARGS_ANY,
1470 1466
              [DEBUG_OPT, m_force_multi,
1471
               make_option("-e", "--extra", dest="extra_args",
1472
                           help="Extra arguments for the instance's kernel",
1473
                           default=None, type="string", metavar="<PARAMS>"),
1474 1467
               make_option("-t", "--type", dest="reboot_type",
1475 1468
                           help="Type of reboot: soft/hard/full",
1476 1469
                           default=constants.INSTANCE_REBOOT_HARD,

Also available in: Unified diff