コード例 #1
0
    def _process(self, conn, vm, vmuuid):
        if re.search(r"^guestfs-", vm.get_name()):
            logging.debug("ignore libvirt/guestfs temporary VM %s",
                          vm.get_name())
            return

        g = GuestFS()
        prettyvm = conn.get_uri() + ":" + vm.get_name()
        ignore = vmuuid

        disks = []
        for disk in vm.get_disk_devices():
            if (disk.path and (disk.type == "block" or disk.type == "file")
                    and not disk.device == "cdrom"):
                disks.append(disk)

        if not disks:
            logging.debug("%s: nothing to inspect", prettyvm)
            return

        # Add the disks.  Note they *must* be added with readonly flag set.
        for disk in disks:
            path = disk.path
            driver_type = disk.driver_type

            if not (os.path.exists(path) and os.access(path, os.R_OK)):
                logging.debug("%s: cannot access '%s', skipping inspection",
                              prettyvm, path)
                return

            g.add_drive_opts(path, readonly=1, format=driver_type)

        g.launch()

        # Inspect the operating system.
        roots = g.inspect_os()
        if len(roots) == 0:
            logging.debug("%s: no operating systems found", prettyvm)
            return

        # Arbitrarily pick the first root device.
        root = roots[0]

        # Inspection results.
        typ = g.inspect_get_type(root)  # eg. "linux"
        distro = g.inspect_get_distro(root)  # eg. "fedora"
        major_version = g.inspect_get_major_version(root)  # eg. 14
        minor_version = g.inspect_get_minor_version(root)  # eg. 0
        hostname = g.inspect_get_hostname(root)  # string
        product_name = g.inspect_get_product_name(root)  # string
        product_variant = g.inspect_get_product_variant(root)  # string

        # For inspect_list_applications and inspect_get_icon we
        # require that the guest filesystems are mounted.  However
        # don't fail if this is not possible (I'm looking at you,
        # FreeBSD).
        filesystems_mounted = False
        try:
            # Mount up the disks, like guestfish --ro -i.

            # Sort keys by length, shortest first, so that we end up
            # mounting the filesystems in the correct order.
            mps = list(g.inspect_get_mountpoints(root))

            def compare(a, b):
                if len(a[0]) > len(b[0]):
                    return 1
                elif len(a[0]) == len(b[0]):
                    return 0
                else:
                    return -1

            mps.sort(compare)

            for mp_dev in mps:
                try:
                    g.mount_ro(mp_dev[1], mp_dev[0])
                except:
                    logging.exception(
                        "%s: exception mounting %s on %s "
                        "(ignored)", prettyvm, mp_dev[1], mp_dev[0])

            filesystems_mounted = True
        except:
            logging.exception("%s: exception while mounting disks (ignored)",
                              prettyvm)

        icon = None
        apps = None
        if filesystems_mounted:
            # string containing PNG data
            icon = g.inspect_get_icon(root, favicon=0, highquality=1)
            if icon == "":
                icon = None

            # Inspection applications.
            apps = g.inspect_list_applications(root)

        # Force the libguestfs handle to close right now.
        del g

        # Log what we found.
        logging.debug("%s: detected operating system: %s %s %d.%d (%s)",
                      prettyvm, typ, distro, major_version, minor_version,
                      product_name)
        logging.debug("hostname: %s", hostname)
        if icon:
            logging.debug("icon: %d bytes", len(icon))
        if apps:
            logging.debug("# apps: %d", len(apps))

        data = vmmInspectionData()
        data.type = str(type)
        data.distro = str(distro)
        data.major_version = int(major_version)
        data.minor_version = int(minor_version)
        data.hostname = str(hostname)
        data.product_name = str(product_name)
        data.product_variant = str(product_variant)
        data.icon = icon
        data.applications = list(apps)

        self._set_vm_inspection_data(vm, data)
コード例 #2
0
ファイル: filesystem.py プロジェクト: noxdafox/vminspect
class FileSystem:
    """Convenience wrapper over GuestFS instance.

    Simplifies some common routines.

    Automatically translates paths according to the contained File System.

    """

    def __init__(self, disk_path):
        self._root = None
        self._handler = GuestFS()
        self._disk_path = disk_path

    def __enter__(self):
        self.mount()

        return self

    def __exit__(self, *_):
        self.umount()

    def __getattr__(self, attr):
        return getattr(self._handler, attr)

    @property
    def osname(self):
        """Returns the Operating System name."""
        return self._handler.inspect_get_type(self._root)

    @property
    def fsroot(self):
        """Returns the file system root."""
        if self.osname == "windows":
            return "{}:\\".format(self._handler.inspect_get_drive_mappings(self._root)[0][0])
        else:
            return self._handler.inspect_get_mountpoints(self._root)[0][0]

    def mount(self, readonly=True):
        """Mounts the given disk.
        It must be called before any other method.

        """
        self._handler.add_drive_opts(self._disk_path, readonly=True)
        self._handler.launch()

        for mountpoint, device in self._inspect_disk():
            if readonly:
                self._handler.mount_ro(device, mountpoint)
            else:
                self._handler.mount(device, mountpoint)

        if self._handler.inspect_get_type(self._root) == "windows":
            self.path = self._windows_path
        else:
            self.path = posix_path

    def _inspect_disk(self):
        """Inspects the disk and returns the mountpoints mapping
        as a list which order is the supposed one for correct mounting.

        """
        roots = self._handler.inspect_os()

        if roots:
            self._root = roots[0]
            return sorted(self._handler.inspect_get_mountpoints(self._root), key=lambda m: len(m[0]))
        else:
            raise RuntimeError("No OS found on the given disk image.")

    def umount(self):
        """Unmounts the disk.

        After this method is called no further action is allowed.

        """
        self._handler.close()

    def download(self, source, destination):
        """Downloads the file on the disk at source into destination."""
        self._handler.download(posix_path(source), destination)

    def ls(self, path):
        """Lists the content at the given path."""
        return self._handler.ls(posix_path(path))

    def nodes(self, path):
        """Iterates over the files and directories contained within the disk
        starting from the given path.

        Yields the path of the nodes.

        """
        path = posix_path(path)

        yield from (self.path(path, e) for e in self._handler.find(path))

    def checksum(self, path, hashtype="sha1"):
        """Returns the checksum of the given path."""
        return self._handler.checksum(hashtype, posix_path(path))

    def checksums(self, path, hashtype="sha1"):
        """Iterates over the files hashes contained within the disk
        starting from the given path.

        The hashtype keyword allows to choose the file hashing algorithm.

        Yields the following values:

            "C:\\Windows\\System32\\NTUSER.DAT", "hash" for windows
            "/home/user/text.txt", "hash" for other FS

        """
        with NamedTemporaryFile(buffering=0) as tempfile:
            self._handler.checksums_out(hashtype, posix_path(path), tempfile.name)

            yield from (
                (self.path(f[1].lstrip(".")), f[0]) for f in (l.decode("utf8").strip().split(None, 1) for l in tempfile)
            )

    def stat(self, path):
        """Retrieves the status of the node at the given path.

        Returns a dictionary.

        """
        return self._handler.stat(posix_path(path))

    def file(self, path):
        """Analogous to Unix file command.
        Returns the type of node at the given path.

        """
        return self._handler.file(posix_path(path))

    def exists(self, path):
        """Returns whether the path exists."""
        return self._handler.exists(posix_path(path))

    def path(self, *segments):
        """Normalizes the path returned by guestfs in the File System format."""
        raise NotImplementedError("FileSystem needs to be mounted first")

    def _windows_path(self, *segments):
        drive = self._handler.inspect_get_drive_mappings(self._root)[0][0]

        return "%s:%s" % (drive, os.path.join(*segments).replace("/", "\\"))
コード例 #3
0
    def _process(self, conn, vm):
        if re.search(r"^guestfs-", vm.get_name()):
            logging.debug("ignore libvirt/guestfs temporary VM %s",
                          vm.get_name())
            return None

        g = GuestFS(close_on_exit=False)
        prettyvm = conn.get_uri() + ":" + vm.get_name()

        g.add_libvirt_dom(vm.get_backend(), readonly=1)

        g.launch()

        # Inspect the operating system.
        roots = g.inspect_os()
        if len(roots) == 0:
            logging.debug("%s: no operating systems found", prettyvm)
            return None

        # Arbitrarily pick the first root device.
        root = roots[0]

        # Inspection results.
        typ = g.inspect_get_type(root)  # eg. "linux"
        distro = g.inspect_get_distro(root)  # eg. "fedora"
        major_version = g.inspect_get_major_version(root)  # eg. 14
        minor_version = g.inspect_get_minor_version(root)  # eg. 0
        hostname = g.inspect_get_hostname(root)  # string
        product_name = g.inspect_get_product_name(root)  # string
        product_variant = g.inspect_get_product_variant(root)  # string

        # For inspect_list_applications and inspect_get_icon we
        # require that the guest filesystems are mounted.  However
        # don't fail if this is not possible (I'm looking at you,
        # FreeBSD).
        filesystems_mounted = False
        try:
            # Mount up the disks, like guestfish --ro -i.

            # Sort keys by length, shortest first, so that we end up
            # mounting the filesystems in the correct order.
            mps = list(g.inspect_get_mountpoints(root))
            def compare(a, b):
                if len(a[0]) > len(b[0]):
                    return 1
                elif len(a[0]) == len(b[0]):
                    return 0
                else:
                    return -1
            mps.sort(compare)

            for mp_dev in mps:
                try:
                    g.mount_ro(mp_dev[1], mp_dev[0])
                except:
                    logging.exception("%s: exception mounting %s on %s "
                                      "(ignored)",
                                      prettyvm, mp_dev[1], mp_dev[0])

            filesystems_mounted = True
        except:
            logging.exception("%s: exception while mounting disks (ignored)",
                              prettyvm)

        icon = None
        apps = None
        if filesystems_mounted:
            # string containing PNG data
            icon = g.inspect_get_icon(root, favicon=0, highquality=1)
            if icon == "":
                icon = None

            # Inspection applications.
            apps = g.inspect_list_applications(root)

        # Force the libguestfs handle to close right now.
        del g

        # Log what we found.
        logging.debug("%s: detected operating system: %s %s %d.%d (%s)",
                      prettyvm, typ, distro, major_version, minor_version,
                      product_name)
        logging.debug("hostname: %s", hostname)
        if icon:
            logging.debug("icon: %d bytes", len(icon))
        if apps:
            logging.debug("# apps: %d", len(apps))

        data = vmmInspectionData()
        data.type = str(type)
        data.distro = str(distro)
        data.major_version = int(major_version)
        data.minor_version = int(minor_version)
        data.hostname = str(hostname)
        data.product_name = str(product_name)
        data.product_variant = str(product_variant)
        data.icon = icon
        data.applications = list(apps)
        data.error = False

        return data
    def _process(self, conn, vm, vmuuid):
        g = GuestFS()
        prettyvm = conn.get_uri() + ":" + vm.get_name()
        ignore = vmuuid

        disks = []
        for disk in vm.get_disk_devices():
            if (disk.path and
                (disk.type == "block" or disk.type == "file") and
                not disk.device == "cdrom"):
                disks.append(disk)

        if not disks:
            logging.debug("%s: nothing to inspect", prettyvm)
            return

        # Add the disks.  Note they *must* be added with readonly flag set.
        for disk in disks:
            path = disk.path
            driver_type = disk.driver_type

            if not (os.path.exists(path) and os.access(path, os.R_OK)):
                logging.debug("%s: cannot access '%s', skipping inspection",
                              prettyvm, path)
                return

            g.add_drive_opts(path, readonly=1, format=driver_type)

        g.launch()

        # Inspect the operating system.
        roots = g.inspect_os()
        if len(roots) == 0:
            logging.debug("%s: no operating systems found", prettyvm)
            return

        # Arbitrarily pick the first root device.
        root = roots[0]

        # Inspection results.
        typ = g.inspect_get_type(root) # eg. "linux"
        distro = g.inspect_get_distro(root) # eg. "fedora"
        major_version = g.inspect_get_major_version(root) # eg. 14
        minor_version = g.inspect_get_minor_version(root) # eg. 0
        hostname = g.inspect_get_hostname(root) # string
        product_name = g.inspect_get_product_name(root) # string

        # Added in libguestfs 1.9.13:
        product_variant = None
        if hasattr(g, "inspect_get_product_variant"):
            product_variant = g.inspect_get_product_variant(root) # string

        # For inspect_list_applications and inspect_get_icon we
        # require that the guest filesystems are mounted.  However
        # don't fail if this is not possible (I'm looking at you,
        # FreeBSD).
        filesystems_mounted = False
        try:
            # Mount up the disks, like guestfish --ro -i.

            # Sort keys by length, shortest first, so that we end up
            # mounting the filesystems in the correct order.
            mps = g.inspect_get_mountpoints(root)
            def compare(a, b):
                if len(a[0]) > len(b[0]):
                    return 1
                elif len(a[0]) == len(b[0]):
                    return 0
                else:
                    return -1
            mps.sort(compare)

            for mp_dev in mps:
                try:
                    g.mount_ro(mp_dev[1], mp_dev[0])
                except:
                    logging.exception("%s: exception mounting %s on %s "
                                      "(ignored)",
                                      prettyvm, mp_dev[1], mp_dev[0])

            filesystems_mounted = True
        except:
            logging.exception("%s: exception while mounting disks (ignored)",
                              prettyvm)

        icon = None
        apps = None
        if filesystems_mounted:
            # Added in libguestfs 1.11.12:
            if hasattr(g, "inspect_get_icon"):
                # string containing PNG data
                icon = g.inspect_get_icon(root, favicon=0, highquality=1)
                if icon == "":
                    icon = None

            # Inspection applications.
            apps = g.inspect_list_applications(root)

        # Force the libguestfs handle to close right now.
        del g

        # Log what we found.
        logging.debug("%s: detected operating system: %s %s %d.%d (%s)",
                      prettyvm, typ, distro, major_version, minor_version,
                      product_name)
        logging.debug("hostname: %s", hostname)
        if icon:
            logging.debug("icon: %d bytes", len(icon))
        if apps:
            logging.debug("# apps: %d", len(apps))

        data = vmmInspectionData()
        data.type = str(type)
        data.distro = str(distro)
        data.major_version = int(major_version)
        data.minor_version = int(minor_version)
        data.hostname = str(hostname)
        data.product_name = str(product_name)
        data.product_variant = str(product_variant)
        data.icon = str(icon)
        data.applications = list(apps)

        self._set_vm_inspection_data(vm, data)
コード例 #5
0
ファイル: filesystem.py プロジェクト: wuhao4u/vminspect
class FileSystem:
    """Convenience wrapper over GuestFS instance.

    Simplifies some common routines.

    Automatically translates paths according to the contained File System.

    """
    def __init__(self, disk_path):
        self._root = None
        self._handler = GuestFS()

        self.disk_path = disk_path

    def __enter__(self):
        self.mount()

        return self

    def __exit__(self, *_):
        self.umount()

    def __getattr__(self, attr):
        return getattr(self._handler, attr)

    @property
    def osname(self):
        """Returns the Operating System name."""
        return self._handler.inspect_get_type(self._root)

    @property
    def fsroot(self):
        """Returns the file system root."""
        if self.osname == 'windows':
            return '{}:\\'.format(
                self._handler.inspect_get_drive_mappings(self._root)[0][0])
        else:
            return self._handler.inspect_get_mountpoints(self._root)[0][0]

    def mount(self, readonly=True):
        """Mounts the given disk.
        It must be called before any other method.

        """
        self._handler.add_drive_opts(self.disk_path, readonly=True)
        self._handler.launch()

        for mountpoint, device in self._inspect_disk():
            if readonly:
                self._handler.mount_ro(device, mountpoint)
            else:
                self._handler.mount(device, mountpoint)

        if self._handler.inspect_get_type(self._root) == 'windows':
            self.path = self._windows_path
        else:
            self.path = posix_path

    def _inspect_disk(self):
        """Inspects the disk and returns the mountpoints mapping
        as a list which order is the supposed one for correct mounting.

        """
        roots = self._handler.inspect_os()

        if roots:
            self._root = roots[0]
            return sorted(self._handler.inspect_get_mountpoints(self._root),
                          key=lambda m: len(m[0]))
        else:
            raise RuntimeError("No OS found on the given disk image.")

    def umount(self):
        """Unmounts the disk.

        After this method is called no further action is allowed.

        """
        self._handler.close()

    def download(self, source, destination):
        """Downloads the file on the disk at source into destination."""
        self._handler.download(posix_path(source), destination)

    def ls(self, path):
        """Lists the content at the given path."""
        return self._handler.ls(posix_path(path))

    def nodes(self, path):
        """Iterates over the files and directories contained within the disk
        starting from the given path.

        Yields the path of the nodes.

        """
        path = posix_path(path)

        yield from (self.path(path, e) for e in self._handler.find(path))

    def checksum(self, path, hashtype='sha1'):
        """Returns the checksum of the given path."""
        return self._handler.checksum(hashtype, posix_path(path))

    def checksums(self, path, hashtype='sha1'):
        """Iterates over the files hashes contained within the disk
        starting from the given path.

        The hashtype keyword allows to choose the file hashing algorithm.

        Yields the following values:

            "C:\\Windows\\System32\\NTUSER.DAT", "hash" for windows
            "/home/user/text.txt", "hash" for other FS

        """
        with NamedTemporaryFile(buffering=0) as tempfile:
            self._handler.checksums_out(hashtype, posix_path(path),
                                        tempfile.name)

            yield from ((self.path(f[1].lstrip('.')), f[0])
                        for f in (l.decode('utf8').strip().split(None, 1)
                                  for l in tempfile))

    def stat(self, path):
        """Retrieves the status of the node at the given path.

        Returns a dictionary.

        """
        return self._handler.stat(posix_path(path))

    def file(self, path):
        """Analogous to Unix file command.
        Returns the type of node at the given path.

        """
        return self._handler.file(posix_path(path))

    def exists(self, path):
        """Returns whether the path exists."""
        return self._handler.exists(posix_path(path))

    def path(self, *segments):
        """Normalizes the path returned by guestfs in the File System format."""
        raise NotImplementedError("FileSystem needs to be mounted first")

    def _windows_path(self, *segments):
        drive = self._handler.inspect_get_drive_mappings(self._root)[0][0]

        return "%s:%s" % (drive, os.path.join(*segments).replace('/', '\\'))