return block_devices
-def StartInstance(instance):
+def StartInstance(instance, startup_paused):
"""Start an instance.
@type instance: L{objects.Instance}
@param instance: the instance object
+ @type startup_paused: bool
+ @param instance: pause instance at startup?
@rtype: None
"""
try:
block_devices = _GatherAndLinkBlockDevs(instance)
hyper = hypervisor.GetHypervisor(instance.hypervisor)
- hyper.StartInstance(instance, block_devices)
+ hyper.StartInstance(instance, block_devices, startup_paused)
except errors.BlockDeviceError, err:
_Fail("Block device error: %s", err, exc=True)
except errors.HypervisorError, err:
"SRC_DIR_OPT",
"SRC_NODE_OPT",
"SUBMIT_OPT",
+ "STARTUP_PAUSED_OPT",
"STATIC_OPT",
"SYNC_OPT",
"TAG_ADD_OPT",
" disk templates, e.g. %s)" %
utils.CommaJoin(constants.DTS_INT_MIRROR))
+STARTUP_PAUSED_OPT = cli_option("--paused", dest="startup_paused",
+ action="store_true", default=False,
+ help="Pause instance at startup")
+
#: Options provided by all commands
COMMON_OPTS = [DEBUG_OPT]
op = opcodes.OpInstanceStartup(instance_name=name,
force=opts.force,
ignore_offline_nodes=opts.ignore_offline,
- no_remember=opts.no_remember)
+ no_remember=opts.no_remember,
+ startup_paused=opts.startup_paused)
# do not add these parameters to the opcode unless they're defined
if opts.hvparams:
op.hvparams = opts.hvparams
m_node_tags_opt, m_pri_node_tags_opt, m_sec_node_tags_opt,
m_inst_tags_opt, m_clust_opt, m_inst_opt, SUBMIT_OPT, HVOPTS_OPT,
BACKEND_OPT, DRY_RUN_OPT, PRIORITY_OPT, IGNORE_OFFLINE_OPT,
- NO_REMEMBER_OPT],
+ NO_REMEMBER_OPT, STARTUP_PAUSED_OPT],
"<instance>", "Starts an instance"),
'reboot': (
GenericManyOps("reboot", _RebootInstance), [ArgInstance()],
_StartInstanceDisks(self, instance, force)
result = self.rpc.call_instance_start(node_current, instance,
- self.op.hvparams, self.op.beparams)
+ self.op.hvparams, self.op.beparams,
+ self.op.startup_paused)
msg = result.fail_msg
if msg:
_ShutdownInstanceDisks(self, instance)
self.LogInfo("Instance %s was already stopped, starting now",
instance.name)
_StartInstanceDisks(self, instance, ignore_secondaries)
- result = self.rpc.call_instance_start(node_current, instance, None, None)
+ result = self.rpc.call_instance_start(node_current, instance,
+ None, None, False)
msg = result.fail_msg
if msg:
_ShutdownInstanceDisks(self, instance)
_ShutdownInstanceDisks(self, instance)
raise errors.OpExecError("Can't activate the instance's disks")
- result = self.rpc.call_instance_start(target_node, instance, None, None)
+ result = self.rpc.call_instance_start(target_node, instance,
+ None, None, False)
msg = result.fail_msg
if msg:
_ShutdownInstanceDisks(self, instance)
self.cfg.Update(iobj, feedback_fn)
logging.info("Starting instance %s on node %s", instance, pnode_name)
feedback_fn("* starting instance...")
- result = self.rpc.call_instance_start(pnode_name, iobj, None, None)
+ result = self.rpc.call_instance_start(pnode_name, iobj,
+ None, None, False)
result.Raise("Could not start instance")
return list(iobj.all_nodes)
not self.op.remove_instance):
assert not activate_disks
feedback_fn("Starting instance %s" % instance.name)
- result = self.rpc.call_instance_start(src_node, instance, None, None)
+ result = self.rpc.call_instance_start(src_node, instance,
+ None, None, False)
msg = result.fail_msg
if msg:
feedback_fn("Failed to start instance: %s" % msg)
def __init__(self):
pass
- def StartInstance(self, instance, block_devices):
+ def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance."""
raise NotImplementedError
data.append((file_name, 0, 0, 0, 0, 0))
return data
- def StartInstance(self, instance, block_devices):
+ def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance.
For the chroot manager, we try to mount the block device and
file_name = self._InstanceFile(instance_name)
utils.RemoveFile(file_name)
- def StartInstance(self, instance, block_devices):
+ def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance.
For the fake hypervisor, it just creates a file in the base dir,
data.append(info)
return data
- def _GenerateKVMRuntime(self, instance, block_devices):
+ def _GenerateKVMRuntime(self, instance, block_devices, startup_paused):
"""Generate KVM information to start an instance.
"""
kvm_cmd.extend(['-daemonize'])
if not instance.hvparams[constants.HV_ACPI]:
kvm_cmd.extend(['-no-acpi'])
+ if startup_paused:
+ kvm_cmd.extend(['-S'])
hvp = instance.hvparams
boot_disk = hvp[constants.HV_BOOT_ORDER] == constants.HT_BO_DISK
for filename in temp_files:
utils.RemoveFile(filename)
- def StartInstance(self, instance, block_devices):
+ def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance.
"""
self._CheckDown(instance.name)
- kvm_runtime = self._GenerateKVMRuntime(instance, block_devices)
+ kvm_runtime = self._GenerateKVMRuntime(instance, block_devices, startup_paused)
self._SaveKVMRuntime(instance, kvm_runtime)
self._ExecuteKVMRuntime(instance, kvm_runtime)
return "\n".join(out) + "\n"
- def StartInstance(self, instance, block_devices):
+ def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance.
For LCX, we try to mount the block device and execute 'lxc-start'.
xm_list = self._GetXMList(False)
return xm_list
- def StartInstance(self, instance, block_devices):
+ def StartInstance(self, instance, block_devices, startup_paused):
"""Start an instance.
"""
self._WriteConfigFile(instance, block_devices)
- result = utils.RunCmd(["xm", "create", instance.name])
+ cmd = ["xm", "create"]
+ if startup_paused:
+ cmd.extend(["--paused"])
+ cmd.extend([instance.name])
+ result = utils.RunCmd(cmd)
if result.failed:
raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
_PMigrationTargetNode = ("target_node", None, ht.TMaybeString,
"Target node for shared-storage instances")
+_PStartupPaused = ("startup_paused", False, ht.TBool,
+ "Pause instance at startup")
+
+
#: OP_ID conversion regular expression
_OPID_RE = re.compile("([a-z])([A-Z])")
"Temporary hypervisor parameters, hypervisor-dependent"),
("beparams", ht.EmptyDict, ht.TDict, "Temporary backend parameters"),
_PNoRemember,
+ _PStartupPaused,
]
return self._SingleNodeCall(node, "bridges_exist", [bridges_list])
@_RpcTimeout(_TMO_NORMAL)
- def call_instance_start(self, node, instance, hvp, bep):
+ def call_instance_start(self, node, instance, hvp, bep, startup_paused):
"""Starts an instance.
This is a single-node call.
"""
idict = self._InstDict(instance, hvp=hvp, bep=bep)
- return self._SingleNodeCall(node, "instance_start", [idict])
+ return self._SingleNodeCall(node, "instance_start", [idict, startup_paused])
@_RpcTimeout(_TMO_NORMAL)
def call_instance_shutdown(self, node, instance, timeout):
"""Start an instance.
"""
- instance = objects.Instance.FromDict(params[0])
- return backend.StartInstance(instance)
+ (instance_name, startup_paused) = params
+ instance = objects.Instance.FromDict(instance_name)
+ return backend.StartInstance(instance, startup_paused)
@staticmethod
def perspective_migration_info(params):
| --tags \| --node-tags \| --pri-node-tags \| --sec-node-tags]
| [{-H|--hypervisor-parameters} ``key=value...``]
| [{-B|--backend-parameters} ``key=value...``]
-| [--submit]
+| [--submit] [--paused]
| {*name*...}
Starts one or more instances, depending on the following options. The
will start all instances in the cluster on secondary nodes with the
tags given as arguments
-
Note that although you can pass more than one selection option, the
last one wins, so in order to guarantee the desired result, don't pass
more than one such option.
completion. The job ID will be shown so that it can be examined via
**gnt-job info**.
+The ``--paused`` option is only valid for Xen and kvm hypervisors. This
+pauses the instance at the start of bootup, awaiting ``gnt-instance
+console`` to unpause it, allowing the entire boot process to be
+monitored for debugging.
+
Example::
# gnt-instance start instance1.example.com
HVM instance, use a VNC client with the connection info from the
**info** command.
+For Xen/kvm instances, if the instance is paused, this attempts to
+unpause the instance after waiting a few seconds for the connection to
+the console to be made.
+
Example::
# gnt-instance console instance1.example.com