From 246e3c9c591ffc54ce5591aa93cc178c060d8af9 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 1 Jun 2016 14:32:56 +0100 Subject: [PATCH] virtinst: Add --transient flag. If this flag is specified, --import|--boot will create a transient libvirt domain, ie. one which goes away when the guest shuts down or the host is rebooted. (crobinso: some tweaks and tests) --- man/virt-install.pod | 9 +++++++++ tests/clitest.py | 1 + virt-install | 35 ++++++++++++++++++++++++----------- virtinst/guest.py | 14 +++++++++----- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/man/virt-install.pod b/man/virt-install.pod index 40e18449..a1229c80 100644 --- a/man/virt-install.pod +++ b/man/virt-install.pod @@ -1576,6 +1576,15 @@ Show program's version number and exit Set the autostart flag for a domain. This causes the domain to be started on host boot up. +=item B<--transient> + +Use --import or --boot and --transient if you want a transient libvirt +VM. These VMs exist only until the domain is shut down or the host +server is restarted. Libvirt forgets the XML configuration of the VM +after either of these events. Note that the VM's disks will not be +deleted. See: +L + =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. diff --git a/tests/clitest.py b/tests/clitest.py index 0ecffccd..2625142c 100644 --- a/tests/clitest.py +++ b/tests/clitest.py @@ -797,6 +797,7 @@ c = vinst.add_category("console-tests", "--pxe --nodisks") c.add_valid("--nographics") # mock virsh console waiting c.add_valid("--graphics vnc --noreboot") # mock virt-viewer waiting, with noreboot magic c.add_invalid("--noautoconsole --wait 1") # --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") # --transient handling diff --git a/virt-install b/virt-install index 5a3065cb..b48f2108 100755 --- a/virt-install +++ b/virt-install @@ -449,6 +449,9 @@ _cdrom_location_man_page = _("See the man page for examples of " def check_option_collisions(options, guest): + if options.noreboot and options.transient: + fail(_("--noreboot and --transient can not be specified together")) + # Install collisions if sum([bool(l) for l in [options.pxe, options.location, options.cdrom, options.import_install]]) > 1: @@ -688,13 +691,14 @@ def start_install(guest, options): start_time = time.time() # Do first install phase - guest.start_install(meter=meter, doboot=not options.noreboot) + guest.start_install(meter=meter, doboot=not options.noreboot, + transient=options.transient) cli.connect_console(guest, conscb, wait_on_console) - check_domain(guest, conscb, + check_domain(guest, conscb, options.transient, wait_on_install, wait_time, start_time) print_stdout(_("Domain creation completed.")) - if not guest.domain.isActive(): + if not options.transient and not guest.domain.isActive(): if options.noreboot or not guest.installer.has_install_phase(): print_stdout( _("You can restart your domain by running:\n %s") % @@ -715,21 +719,27 @@ def start_install(guest, options): cli.install_fail(guest) -def check_domain(guest, conscb, wait_for_install, wait_time, start_time): +def check_domain(guest, conscb, transient, + wait_for_install, wait_time, start_time): """ Make sure domain ends up in expected state, and wait if for install to complete if requested """ - # Wait a bit so info is accurate def check_domain_inactive(): - dominfo = guest.domain.info() - state = dominfo[0] - logging.debug("Domain state after install: %s", state) + try: + dominfo = guest.domain.info() + state = dominfo[0] + logging.debug("Domain state after install: %s", state) - if state == libvirt.VIR_DOMAIN_CRASHED: - fail(_("Domain has crashed.")) + if state == libvirt.VIR_DOMAIN_CRASHED: + fail(_("Domain has crashed.")) - return not guest.domain.isActive() + return not guest.domain.isActive() + except libvirt.libvirtError, e: + if transient and e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN: + logging.debug("transient VM shutdown and disappeared.") + return True + raise if check_domain_inactive(): return @@ -927,6 +937,9 @@ def parse_args(): misc.add_argument("--autostart", action="store_true", dest="autostart", default=False, help=_("Have domain autostart on host boot up.")) + misc.add_argument("--transient", action="store_true", dest="transient", + default=False, + help=_("Create a transient domain.")) misc.add_argument("--wait", type=int, dest="wait", help=_("Minutes to wait for install to complete.")) diff --git a/virtinst/guest.py b/virtinst/guest.py index 8e574d59..8e7aef7e 100644 --- a/virtinst/guest.py +++ b/virtinst/guest.py @@ -382,7 +382,7 @@ class Guest(XMLBuilder): return install_xml, final_xml - def _create_guest(self, meter, install_xml, final_xml, doboot): + def _create_guest(self, meter, install_xml, final_xml, doboot, transient): """ Actually do the XML logging, guest defining/creating @@ -392,10 +392,11 @@ class Guest(XMLBuilder): meter = util.ensure_meter(meter) meter.start(size=None, text=meter_label) - if doboot or self.installer.has_install_phase(): + if doboot or transient or self.installer.has_install_phase(): self.domain = self.conn.createXML(install_xml or final_xml, 0) - self.domain = self.conn.defineXML(final_xml) + if not transient: + self.domain = self.conn.defineXML(final_xml) meter.end(0) try: @@ -428,7 +429,8 @@ class Guest(XMLBuilder): ############## def start_install(self, meter=None, - dry=False, return_xml=False, doboot=True): + dry=False, return_xml=False, + doboot=True, transient=False): """ Begin the guest install (stage1). @param return_xml: Don't create the guest, just return generated XML @@ -455,7 +457,9 @@ class Guest(XMLBuilder): self.check_vm_collision(self.conn, self.name, do_remove=self.replace) - self._create_guest(meter, install_xml, final_xml, doboot) + self._create_guest(meter, install_xml, final_xml, + doboot, transient) + # Set domain autostart flag if requested self._flag_autostart() finally: