mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-01-10 01:18:03 +03:00
virt-install: add --destroy-on-exit
This makes the console window behave like a raw qemu command line: when the user closes it, the VM is hard powered off.
This commit is contained in:
parent
96ac896e1a
commit
42a96cfd59
@ -1664,6 +1664,13 @@ after either of these events. Note that the VM's disks will not be
|
||||
deleted. See:
|
||||
L<https://wiki.libvirt.org/page/VM_lifecycle#Transient_guest_domains_vs_Persistent_guest_domains>
|
||||
|
||||
=item B<--destroy-on-exit>
|
||||
|
||||
When the VM console window is exited, destroy (force poweroff) the VM.
|
||||
If you combine this with --transient, this makes the virt-install command
|
||||
work similar to qemu, where the VM is shutdown when the console window
|
||||
is closed by the user.
|
||||
|
||||
=item B<--print-xml> [STEP]
|
||||
|
||||
Print the generated XML of the guest, instead of defining it. By default this WILL do storage creation (can be disabled with --dry-run). This option implies --quiet.
|
||||
|
@ -824,6 +824,8 @@ c.add_valid("--file %(NEWIMG1)s --file-size .00001 --nonsparse") # Nonexistent
|
||||
|
||||
c = vinst.add_category("console-tests", "--pxe --nodisks")
|
||||
c.add_valid("", grep="testsuite console command: ['virt-viewer'") # mock default graphics+virt-viewer usage
|
||||
c.add_valid("--destroy-on-exit", grep="Restarting guest.\n") # destroy-on-exit
|
||||
c.add_valid("--transient --destroy-on-exit", grep="Domain creation completed.") # destroy-on-exit + transient
|
||||
c.add_valid("--graphics vnc --noreboot", grep="testsuite console command: ['virt-viewer'") # mock virt-viewer waiting, with noreboot magic
|
||||
c.add_invalid("--noautoconsole --wait 1", grep="Installation has exceeded specified time limit") # --wait 1 is converted to 1 second if we are in the test suite, so this should actually touch the wait machinery. however in this case it exits with failure
|
||||
c.add_valid("--nographics --transient", grep="testsuite console command: ['virsh'") # --transient handling
|
||||
|
@ -113,7 +113,7 @@ def main(conn=None):
|
||||
elif not options.dry:
|
||||
print_stdout(_("Creating guest '%s'.") % guest.name)
|
||||
domain = installer.start_install(guest)
|
||||
cli.connect_console(guest, domain, conscb, True)
|
||||
cli.connect_console(guest, domain, conscb, True, False)
|
||||
except Exception:
|
||||
converter.cleanup()
|
||||
raise
|
||||
|
29
virt-install
29
virt-install
@ -6,6 +6,7 @@
|
||||
# See the COPYING file in the top-level directory.
|
||||
|
||||
import argparse
|
||||
import atexit
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
@ -600,7 +601,12 @@ def start_install(guest, installer, options):
|
||||
doboot=not options.noreboot,
|
||||
transient=options.transient,
|
||||
autostart=options.autostart)
|
||||
cli.connect_console(guest, domain, conscb, wait_on_console)
|
||||
|
||||
if options.destroy_on_exit:
|
||||
atexit.register(_destroy_on_exit, domain)
|
||||
|
||||
cli.connect_console(guest, domain, conscb, wait_on_console,
|
||||
options.destroy_on_exit)
|
||||
check_domain(installer, domain, conscb, options.transient,
|
||||
wait_on_install, wait_time, start_time)
|
||||
|
||||
@ -613,7 +619,8 @@ def start_install(guest, installer, options):
|
||||
else:
|
||||
print_stdout(_("Restarting guest."))
|
||||
domain.create()
|
||||
cli.connect_console(guest, domain, conscb, True)
|
||||
cli.connect_console(guest, domain, conscb, True,
|
||||
options.destroy_on_exit)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logging.debug("", exc_info=True)
|
||||
@ -656,7 +663,8 @@ def check_domain(installer, domain, conscb, transient,
|
||||
# just closed the console and the VM is still running. In the
|
||||
# the former case, libvirt may not have caught up yet with the
|
||||
# VM having exited, so wait a bit and check again
|
||||
time.sleep(2)
|
||||
if not cli.in_testsuite():
|
||||
time.sleep(2)
|
||||
if check_domain_inactive():
|
||||
return
|
||||
|
||||
@ -852,6 +860,9 @@ def parse_args():
|
||||
help=_("Have domain autostart on host boot up."))
|
||||
misc.add_argument("--transient", action="store_true", default=False,
|
||||
help=_("Create a transient domain."))
|
||||
misc.add_argument("--destroy-on-exit", action="store_true", default=False,
|
||||
help=_("Force power off the domain when the console "
|
||||
"viewer is closed."))
|
||||
misc.add_argument("--wait", type=int,
|
||||
help=_("Minutes to wait for install to complete."))
|
||||
|
||||
@ -865,6 +876,18 @@ def parse_args():
|
||||
# main() handling #
|
||||
###################
|
||||
|
||||
# Catchall for destroying the VM on ex. ctrl-c
|
||||
def _destroy_on_exit(domain):
|
||||
try:
|
||||
isactive = bool(domain and domain.isActive())
|
||||
if isactive:
|
||||
domain.destroy()
|
||||
except libvirt.libvirtError as e:
|
||||
if e.get_error_code() != libvirt.VIR_ERR_NO_DOMAIN:
|
||||
logging.debug("Error invoking atexit destroy_on_exit",
|
||||
exc_info=True)
|
||||
|
||||
|
||||
def set_test_stub_options(options):
|
||||
# Set some basic options that will let virt-install succeed. Helps
|
||||
# save boiler plate typing when testing new command line additions
|
||||
|
@ -358,13 +358,11 @@ def validate_disk(dev, warn_overwrite=False):
|
||||
|
||||
|
||||
def _run_console(domain, args):
|
||||
ignore = domain
|
||||
logging.debug("Running: %s", " ".join(args))
|
||||
if in_testsuite():
|
||||
print_stdout("testsuite console command: %s" % args)
|
||||
# Add this destroy() in here to trigger more virt-install code
|
||||
# for the test suite
|
||||
domain.destroy()
|
||||
return None
|
||||
args = ["/bin/true"]
|
||||
|
||||
child = os.fork()
|
||||
if child:
|
||||
@ -398,7 +396,7 @@ def _txt_console(guest, domain):
|
||||
return _run_console(domain, args)
|
||||
|
||||
|
||||
def connect_console(guest, domain, consolecb, wait):
|
||||
def connect_console(guest, domain, consolecb, wait, destroy_on_exit):
|
||||
"""
|
||||
Launched the passed console callback for the already defined
|
||||
domain. If domain isn't running, return an error.
|
||||
@ -416,6 +414,10 @@ def connect_console(guest, domain, consolecb, wait):
|
||||
except OSError as e:
|
||||
logging.debug("waitpid error: %s", e)
|
||||
|
||||
if destroy_on_exit and domain.isActive():
|
||||
logging.debug("console exited and destroy_on_exit passed, destroying")
|
||||
domain.destroy()
|
||||
|
||||
|
||||
def get_console_cb(guest):
|
||||
gdevs = guest.devices.graphics
|
||||
|
Loading…
Reference in New Issue
Block a user