virt-manager

changeset 1589:976f202f5dbd

create: Make sure we restart new VMs the correct number of times

This means booting live cd's after initial creation, doing a post install
boot for most other installs, and booting windows twice for the 2 stage
install.
author Cole Robinson <crobinso@redhat.com>
date Sun Feb 28 19:40:06 2010 -0500 (2010-02-28)
parents c9d3c8dec04f
children 1cfeb4fd523d
files src/virtManager/create.py src/virtManager/domain.py src/virtManager/util.py
line diff
     1.1 --- a/src/virtManager/create.py	Sat Feb 27 10:42:43 2010 -0500
     1.2 +++ b/src/virtManager/create.py	Sun Feb 28 19:40:06 2010 -0500
     1.3 @@ -1531,13 +1531,10 @@
     1.4              self.failed_guest = self.guest
     1.5              return
     1.6  
     1.7 -        # Ensure new VM is loaded
     1.8 -        # FIXME: Hmm, shouldn't we emit a signal here rather than do this?
     1.9 -        self.conn.tick(noStatsUpdate=True)
    1.10 +        vm = self.conn.get_vm(guest.uuid)
    1.11  
    1.12          if self.config.get_console_popup() == 1:
    1.13              # user has requested console on new created vms only
    1.14 -            vm = self.conn.get_vm(guest.uuid)
    1.15              gtype = vm.get_graphics_console()[0]
    1.16              if gtype == "vnc":
    1.17                  self.emit("action-show-console", self.conn.get_uri(),
    1.18 @@ -1566,6 +1563,22 @@
    1.19                  logging.error("Guest install did not return a domain")
    1.20              else:
    1.21                  logging.debug("Install completed")
    1.22 +
    1.23 +            # Make sure we pick up the domain object
    1.24 +            self.conn.tick(noStatsUpdate=True)
    1.25 +            vm = self.conn.get_vm(guest.uuid)
    1.26 +
    1.27 +            if vm.is_shutoff():
    1.28 +                # Domain is already shutdown, but no error was raised.
    1.29 +                # Probably means guest had no 'install' phase, as in
    1.30 +                # for live cds. Try to restart the domain.
    1.31 +                vm.startup()
    1.32 +            else:
    1.33 +                # Register a status listener, which will restart the
    1.34 +                # guest after the install has finished
    1.35 +                util.connect_opt_out(vm, "status-changed",
    1.36 +                                     self.check_install_status, guest)
    1.37 +
    1.38          except:
    1.39              (_type, value, stacktrace) = sys.exc_info ()
    1.40  
    1.41 @@ -1578,6 +1591,36 @@
    1.42          if error:
    1.43              asyncjob.set_error(error, details)
    1.44  
    1.45 +    def check_install_status(self, vm, ignore1, ignore2, virtinst_guest=None):
    1.46 +        if vm.is_crashed():
    1.47 +            logging.debug("VM crashed, cancelling install plans.")
    1.48 +            return True
    1.49 +
    1.50 +        if not vm.is_shutoff():
    1.51 +            return
    1.52 +
    1.53 +        try:
    1.54 +            if virtinst_guest:
    1.55 +                continue_inst = virtinst_guest.get_continue_inst()
    1.56 +
    1.57 +                if continue_inst:
    1.58 +                    logging.debug("VM needs a 2 stage install, continuing.")
    1.59 +                    # Continue the install, then reconnect this opt
    1.60 +                    # out handler, removing the virtinst_guest which
    1.61 +                    # will force one final restart.
    1.62 +                    virtinst_guest.continue_install()
    1.63 +                    util.connect_opt_out(vm, "status-changed",
    1.64 +                                         self.check_install_status, None)
    1.65 +                    return True
    1.66 +
    1.67 +            logging.debug("Install should be completed, starting VM.")
    1.68 +            vm.startup()
    1.69 +        except Exception, e:
    1.70 +            self.err.show_err(_("Error continue install: %s") % str(e),
    1.71 +                              "".join(traceback.format_exc()))
    1.72 +
    1.73 +        return True
    1.74 +
    1.75      def pretty_storage(self, size):
    1.76          return "%.1f Gb" % float(size)
    1.77  
     2.1 --- a/src/virtManager/domain.py	Sat Feb 27 10:42:43 2010 -0500
     2.2 +++ b/src/virtManager/domain.py	Sun Feb 28 19:40:06 2010 -0500
     2.3 @@ -1051,6 +1051,12 @@
     2.4      def disk_io_vector_limit(self, limit):
     2.5          return self.in_out_vector_limit(self.disk_io_vector(), limit)
     2.6  
     2.7 +    def is_shutoff(self):
     2.8 +        return self.status() == libvirt.VIR_DOMAIN_SHUTOFF
     2.9 +
    2.10 +    def is_crashed(self):
    2.11 +        return self.status() == libvirt.VIR_DOMAIN_CRASHED
    2.12 +
    2.13      def is_stoppable(self):
    2.14          return self.status() in [libvirt.VIR_DOMAIN_RUNNING,
    2.15                                   libvirt.VIR_DOMAIN_PAUSED]
    2.16 @@ -1159,8 +1165,10 @@
    2.17  
    2.18          self._update_status()
    2.19  
    2.20 -        self.config.on_stats_enable_net_poll_changed(self.toggle_sample_network_traffic)
    2.21 -        self.config.on_stats_enable_disk_poll_changed(self.toggle_sample_disk_io)
    2.22 +        self.config.on_stats_enable_net_poll_changed(
    2.23 +                                            self.toggle_sample_network_traffic)
    2.24 +        self.config.on_stats_enable_disk_poll_changed(
    2.25 +                                            self.toggle_sample_disk_io)
    2.26  
    2.27          self.getvcpus_supported = support.check_domain_support(self._backend,
    2.28                                              support.SUPPORT_DOMAIN_GETVCPUS)
    2.29 @@ -1176,7 +1184,6 @@
    2.30  
    2.31          # Hook up our own status listeners
    2.32          self.connect("status-changed", self._update_start_vcpus)
    2.33 -        self.connect("status-changed", self._check_install_status)
    2.34  
    2.35      ##########################
    2.36      # Internal virDomain API #
    2.37 @@ -1337,21 +1344,10 @@
    2.38          if maxmem != self.maximum_memory():
    2.39              self._backend.setMaxMemory(maxmem)
    2.40  
    2.41 -
    2.42      ####################
    2.43      # End internal API #
    2.44      ####################
    2.45  
    2.46 -    #########################
    2.47 -    # XML fetching routines #
    2.48 -    #########################
    2.49 -
    2.50 -
    2.51 -
    2.52 -    #############################
    2.53 -    # End XML fetching routines #
    2.54 -    #############################
    2.55 -
    2.56      ###########################
    2.57      # XML/Config Altering API #
    2.58      ###########################
    2.59 @@ -1774,9 +1770,6 @@
    2.60          self._startup_vcpus = None
    2.61          self.vcpu_max_count()
    2.62  
    2.63 -    def _check_install_status(self, ignore, status, oldstatus):
    2.64 -        pass
    2.65 -
    2.66      def _update_status(self, status=None):
    2.67          if status == None:
    2.68              info = self.get_info()
     3.1 --- a/src/virtManager/util.py	Sat Feb 27 10:42:43 2010 -0500
     3.2 +++ b/src/virtManager/util.py	Sun Feb 28 19:40:06 2010 -0500
     3.3 @@ -240,6 +240,33 @@
     3.4  
     3.5      return label
     3.6  
     3.7 +def connect_once(obj, signal, func, *args):
     3.8 +    id_list = []
     3.9 +
    3.10 +    def wrap_func(*wrapargs):
    3.11 +        if id_list:
    3.12 +            obj.disconnect(id_list[0])
    3.13 +
    3.14 +        return func(*wrapargs)
    3.15 +
    3.16 +    conn_id = obj.connect(signal, wrap_func, *args)
    3.17 +    id_list.append(conn_id)
    3.18 +
    3.19 +    return conn_id
    3.20 +
    3.21 +def connect_opt_out(obj, signal, func, *args):
    3.22 +    id_list = []
    3.23 +
    3.24 +    def wrap_func(*wrapargs):
    3.25 +        ret = func(*wrapargs)
    3.26 +        if ret and id_list:
    3.27 +            obj.disconnect(id_list[0])
    3.28 +
    3.29 +    conn_id = obj.connect(signal, wrap_func, *args)
    3.30 +    id_list.append(conn_id)
    3.31 +
    3.32 +    return conn_id
    3.33 +
    3.34  def idle_emit(self, signal, *args):
    3.35      """
    3.36      Safe wrapper for using 'self.emit' with gobject.idle_add