示例#1
0
    def stop(self, label):
        """Stops a virtual machine.
        @param label: virtual machine name.
        @raise DetectorMachineError: if unable to stop.
        """
        log.debug("Stopping vm %s" % label)

        if self._status(label) in [self.POWEROFF, self.ABORTED]:
            raise DetectorMachineError("Trying to stop an already stopped "
                                     "vm %s" % label)

        try:
            proc = subprocess.Popen([self.options.virtualbox.path,
                                     "controlvm", label, "poweroff"],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            # Sometimes VBoxManage stucks when stopping vm so we needed
            # to add a timeout and kill it after that.
            stop_me = 0
            while proc.poll() is None:
                if stop_me < int(self.options_globals.timeouts.vm_state):
                    time.sleep(1)
                    stop_me += 1
                else:
                    log.debug("Stopping vm %s timeouted. Killing" % label)
                    proc.terminate()

            if proc.returncode != 0 and \
                    stop_me < int(self.options_globals.timeouts.vm_state):
                log.debug("VBoxManage exited with error "
                          "powering off the machine")
        except OSError as e:
            raise DetectorMachineError("VBoxManage failed powering off the "
                                     "machine: %s" % e)
        self._wait_status(label, [self.POWEROFF, self.ABORTED, self.SAVED])
示例#2
0
    def stop(self, label):
        """Stops a virtual machine. Kill them all.
        @param label: virtual machine name.
        @raise DetectorMachineError: if unable to stop virtual machine.
        """
        log.debug("Stopping machine %s", label)

        if self._status(label) == self.POWEROFF:
            raise DetectorMachineError("Trying to stop an already stopped "
                                       "machine {0}".format(label))

        # Force virtual machine shutdown.
        conn = self._connect()
        try:
            if not self.vms[label].isActive():
                log.debug(
                    "Trying to stop an already stopped machine %s. "
                    "Skip", label)
            else:
                self.vms[label].destroy()  # Machete's way!
        except libvirt.libvirtError as e:
            raise DetectorMachineError("Error stopping virtual machine "
                                       "{0}: {1}".format(label, e))
        finally:
            self._disconnect(conn)
        # Check state.
        self._wait_status(label, self.POWEROFF)
示例#3
0
    def start(self, label, task):
        """Start a virtual machine.
        @param label: virtual machine name.
        @param task: task object.
        @raise DetectorMachineError: if unable to start.
        """
        log.debug("Starting vm %s" % label)

        if self._status(label) == self.RUNNING:
            raise DetectorMachineError("Trying to start an already "
                                     "started vm %s" % label)

        machine = self.db.view_machine_by_label(label)
        virtualbox_args = [self.options.virtualbox.path, "snapshot", label]
        if machine.snapshot:
            log.debug("Using snapshot {0} for virtual machine "
                      "{1}".format(machine.snapshot, label))
            virtualbox_args.extend(["restore", machine.snapshot])
        else:
            log.debug("Using current snapshot for virtual machine "
                      "{0}".format(label))
            virtualbox_args.extend(["restorecurrent"])

        try:
            if subprocess.call(virtualbox_args,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE):
                raise DetectorMachineError("VBoxManage exited with error "
                                         "restoring the machine's snapshot")
        except OSError as e:
            raise DetectorMachineError("VBoxManage failed restoring the "
                                     "machine: %s" % e)

        self._wait_status(label, self.SAVED)

        try:
            proc = subprocess.Popen([self.options.virtualbox.path,
                                     "startvm",
                                     label,
                                     "--type",
                                     self.options.virtualbox.mode],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            output, err = proc.communicate()
            if err:
                raise OSError(err)
        except OSError as e:
            raise DetectorMachineError("VBoxManage failed starting the machine "
                                     "in %s mode: %s" %
                                     (self.options.virtualbox.mode.upper(), e))

        self._wait_status(label, self.RUNNING)

        # Handle network dumping through the internal VirtualBox functionality.
        if "nictrace" in machine.options:
            self.dump_pcap(label, task)
示例#4
0
    def start(self, label, task):
        """Starts a virtual machine.
        @param label: virtual machine name.
        @param task: task object.
        @raise DetectorMachineError: if unable to start virtual machine.
        """
        log.debug("Starting machine %s", label)

        if self._status(label) != self.POWEROFF:
            msg = "Trying to start a virtual machine that has not " \
                  "been turned off {0}".format(label)
            raise DetectorMachineError(msg)

        conn = self._connect()

        vm_info = self.db.view_machine_by_label(label)

        snapshot_list = self.vms[label].snapshotListNames(flags=0)

        # If a snapshot is configured try to use it.
        if vm_info.snapshot and vm_info.snapshot in snapshot_list:
            # Revert to desired snapshot, if it exists.
            log.debug("Using snapshot {0} for virtual machine "
                      "{1}".format(vm_info.snapshot, label))
            try:
                vm = self.vms[label]
                snapshot = vm.snapshotLookupByName(vm_info.snapshot, flags=0)
                self.vms[label].revertToSnapshot(snapshot, flags=0)
            except libvirt.libvirtError:
                msg = "Unable to restore snapshot {0} on " \
                      "virtual machine {1}".format(vm_info.snapshot, label)
                raise DetectorMachineError(msg)
            finally:
                self._disconnect(conn)
        elif self._get_snapshot(label):
            snapshot = self._get_snapshot(label)
            log.debug("Using snapshot {0} for virtual machine "
                      "{1}".format(snapshot.getName(), label))
            try:
                self.vms[label].revertToSnapshot(snapshot, flags=0)
            except libvirt.libvirtError:
                raise DetectorMachineError("Unable to restore snapshot on "
                                           "virtual machine {0}".format(label))
            finally:
                self._disconnect(conn)
        else:
            self._disconnect(conn)
            raise DetectorMachineError("No snapshot found for virtual machine "
                                       "{0}".format(label))

        # Check state.
        self._wait_status(label, self.RUNNING)
示例#5
0
    def _connect(self):
        """Connects to libvirt subsystem.
        @raise DetectorMachineError: when unable to connect to libvirt.
        """
        # Check if a connection string is available.
        if not self.dsn:
            raise DetectorMachineError("You must provide a proper "
                                       "connection string")

        try:
            return libvirt.open(self.dsn)
        except libvirt.libvirtError:
            raise DetectorMachineError("Cannot connect to libvirt")
示例#6
0
    def _list(self):
        """Lists virtual machines installed.
        @return: virtual machine names list.
        """
        try:
            proc = subprocess.Popen([self.options.virtualbox.path,
                                     "list", "vms"],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            output, _ = proc.communicate()
        except OSError as e:
            raise DetectorMachineError("VBoxManage error listing "
                                     "installed machines: %s" % e)

        machines = []
        for line in output.split("\n"):
            try:
                label = line.split('"')[1]
                if label == "<inaccessible>":
                    log.warning("Found an inaccessible virtual machine, "
                                "please check its state.")
                else:
                    machines.append(label)
            except IndexError:
                continue

        return machines
示例#7
0
    def _wait_status(self, label, state):
        """Waits for a vm status.
        @param label: virtual machine name.
        @param state: virtual machine status, accepts multiple states as list.
        @raise DetectorMachineError: if default waiting timeout expire.
        """
        # This block was originally suggested by Loic Jaquemet.
        waitme = 0
        try:
            current = self._status(label)
        except NameError:
            return

        if isinstance(state, str):
            state = [state]

        while current not in state:
            log.debug(
                "Waiting %i detectorseconds for machine %s to switch "
                "to status %s", waitme, label, state)
            if waitme > int(self.options_globals.timeouts.vm_state):
                raise DetectorMachineError("Timeout hit while for machine {0} "
                                           "to change status".format(label))
            time.sleep(1)
            waitme += 1
            current = self._status(label)
示例#8
0
 def _disconnect(self, conn):
     """Disconnects to libvirt subsystem.
     @raise DetectorMachineError: if cannot disconnect from libvirt.
     """
     try:
         conn.close()
     except libvirt.libvirtError:
         raise DetectorMachineError("Cannot disconnect from libvirt")
示例#9
0
    def _status(self, label):
        """Gets current status of a vm.
        @param label: virtual machine name.
        @return: status string.
        """
        log.debug("Getting status for %s", label)

        # Stetes mapping of python-libvirt.
        # virDomainState
        # VIR_DOMAIN_NOSTATE = 0
        # VIR_DOMAIN_RUNNING = 1
        # VIR_DOMAIN_BLOCKED = 2
        # VIR_DOMAIN_PAUSED = 3
        # VIR_DOMAIN_SHUTDOWN = 4
        # VIR_DOMAIN_SHUTOFF = 5
        # VIR_DOMAIN_CRASHED = 6
        # VIR_DOMAIN_PMSUSPENDED = 7

        conn = self._connect()
        try:
            state = self.vms[label].state(flags=0)
        except libvirt.libvirtError as e:
            raise DetectorMachineError("Error getting status for virtual "
                                       "machine {0}: {1}".format(label, e))
        finally:
            self._disconnect(conn)

        if state:
            if state[0] == 1:
                status = self.RUNNING
            elif state[0] == 3:
                status = self.PAUSED
            elif state[0] == 4 or state[0] == 5:
                status = self.POWEROFF
            else:
                status = self.ERROR

        # Report back status.
        if status:
            self.set_status(label, status)
            return status
        else:
            raise DetectorMachineError("Unable to get status for "
                                       "{0}".format(label))
示例#10
0
 def _list(self):
     """List available virtual machines.
     @raise DetectorMachineError: if unable to list virtual machines.
     """
     conn = self._connect()
     try:
         names = conn.listDefinedDomains()
     except libvirt.libvirtError:
         raise DetectorMachineError("Cannot list domains")
     finally:
         self._disconnect(conn)
     return names
示例#11
0
    def dump_memory(self, label, path):
        """Takes a memory dump.
        @param path: path to where to store the memory dump.
        """

        try:
            proc = subprocess.Popen([self.options.virtualbox.path, "-v"],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            output, err = proc.communicate()

            if proc.returncode != 0:
                # It's quite common for virtualbox crap utility to exit with:
                # VBoxManage: error: Details: code E_ACCESSDENIED (0x80070005)
                # So we just log to debug this.
                log.debug("VBoxManage returns error checking status for "
                          "machine %s: %s", label, err)
        except OSError as e:
            raise DetectorMachineError("VBoxManage failed return it's version: %s" % (e))

        if output[:1] == str(5):
            # VirtualBox version 5.x
            dumpcmd = "dumpvmcore"
        else:
            # VirtualBox version 4.x
            dumpcmd = "dumpguestcore"

        try:
            subprocess.call([self.options.virtualbox.path, "debugvm",
                             label, dumpcmd, "--filename", path],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
            log.info("Successfully generated memory dump for virtual machine "
                     "with label %s to path %s", label, path)
        except OSError as e:
            raise DetectorMachineError("VBoxManage failed to take a memory "
                                     "dump of the machine with label %s: %s" %
                                     (label, e))
示例#12
0
    def dump_memory(self, label, path):
        """Takes a memory dump.
        @param path: path to where to store the memory dump.
        """
        log.debug("Dumping memory for machine %s", label)

        conn = self._connect()
        try:
            self.vms[label].coreDump(path, flags=libvirt.VIR_DUMP_MEMORY_ONLY)
        except libvirt.libvirtError as e:
            raise DetectorMachineError("Error dumping memory virtual machine "
                                       "{0}: {1}".format(label, e))
        finally:
            self._disconnect(conn)
示例#13
0
 def _lookup(self, label):
     """Search for a virtual machine.
     @param conn: libvirt connection handle.
     @param label: virtual machine name.
     @raise DetectorMachineError: if virtual machine is not found.
     """
     conn = self._connect()
     try:
         vm = conn.lookupByName(label)
     except libvirt.libvirtError:
         raise DetectorMachineError("Cannot find machine "
                                    "{0}".format(label))
     finally:
         self._disconnect(conn)
     return vm
示例#14
0
    def _initialize_check(self):
        """Runs all checks when a machine manager is initialized.
        @raise DetectorMachineError: if libvirt version is not supported.
        """
        # Version checks.
        if not self._version_check():
            raise DetectorMachineError("Libvirt version is not supported, "
                                       "please get an updated version")

        # Preload VMs
        self.vms = self._fetch_machines()

        # Base checks. Also attempts to shutdown any machines which are
        # currently still active.
        super(LibVirtMachinery, self)._initialize_check()
示例#15
0
    def _status(self, label):
        """Gets current status of a vm.
        @param label: virtual machine name.
        @return: status string.
        """
        log.debug("Getting status for %s" % label)
        status = None
        try:
            proc = subprocess.Popen([self.options.virtualbox.path,
                                     "showvminfo",
                                     label,
                                     "--machinereadable"],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            output, err = proc.communicate()

            if proc.returncode != 0:
                # It's quite common for virtualbox crap utility to exit with:
                # VBoxManage: error: Details: code E_ACCESSDENIED (0x80070005)
                # So we just log to debug this.
                log.debug("VBoxManage returns error checking status for "
                          "machine %s: %s", label, err)
                status = self.ERROR
        except OSError as e:
            log.warning("VBoxManage failed to check status for machine %s: %s",
                        label, e)
            status = self.ERROR
        if not status:
            for line in output.split("\n"):
                state = re.match(r'VMState="(\w+)"', line, re.M | re.I)
                if state:
                    status = state.group(1)
                    log.debug("Machine %s status %s" % (label, status))
                    status = status.lower()
        # Report back status.
        if status:
            self.set_status(label, status)
            return status
        else:
            raise DetectorMachineError("Unable to get status for %s" % label)
示例#16
0
    def _get_snapshot(self, label):
        """Get current snapshot for virtual machine
        @param label: virtual machine name
        @return None or current snapshot
        @raise DetectorMachineError: if cannot find current snapshot or
                                   when there are too many snapshots available
        """
        def _extract_creation_time(node):
            """Extracts creation time from a KVM vm config file.
            @param node: config file node
            @return: extracted creation time
            """
            xml = ET.fromstring(node.getXMLDesc(flags=0))
            return xml.findtext("./creationTime")

        snapshot = None
        conn = self._connect()
        try:
            vm = self.vms[label]

            # Try to get the currrent snapshot, otherwise fallback on the latest
            # from config file.
            if vm.hasCurrentSnapshot(flags=0):
                snapshot = vm.snapshotCurrent(flags=0)
            else:
                log.debug("No current snapshot, using latest snapshot")

                # No current snapshot, try to get the last one from config file.
                snapshot = sorted(vm.listAllSnapshots(flags=0),
                                  key=_extract_creation_time,
                                  reverse=True)[0]
        except libvirt.libvirtError:
            raise DetectorMachineError("Unable to get snapshot for "
                                       "virtual machine {0}".format(label))
        finally:
            self._disconnect(conn)

        return snapshot