Exemplo n.º 1
0
class VMBackedTestCase(unittest.TestCase):
    """ A class to encapsulate testing of blivet using block devices.

        The basic idea is you create some scratch block devices and then run
        some test code on them.

        :attr:`~.ImageBackedTestCase.disks` defines the set of disk images.

        :meth:`~.ImageBackedTestCase._set_up_storage` is where you specify the
        initial layout of the disks. It will be written to the disk images in
        :meth:`~.ImageBackedTestCase.set_up_storage`.

        You then write test methods as usual that use the disk images, which
        will be cleaned up and removed when each test method finishes.
    """

    initialize_disks = True  # Whether or not to create a disklabel on the disks.

    def set_up_disks(self):
        """ Create disk image files to build the test's storage on.

            If you are actually creating the disk image files here don't forget
            to set the initialize_disks flag so they get a fresh disklabel when
            clear_partitions gets called from create_storage later.
        """

    def _set_up_storage(self):
        """ Schedule creation of storage devices on the disk images.

            .. note::

                The disk images should already be in a populated devicetree.

        """

    def set_up_storage(self):
        """ Create a device stack on top of disk images for this test to run on.

            This will write the configuration to whatever disk images are
            defined in set_up_disks.
        """

        udev.ignored_device_names = [r'^zram']

        #
        # create disk images
        #
        self.set_up_disks()

        #
        # populate the devicetree
        #
        self.blivet.reset()

        if self.initialize_disks:
            for disk in self.blivet.disks:
                self.blivet.initialize_disk(disk)

        #
        # create the rest of the stack
        #
        self._set_up_storage()

        #
        # write configuration to disk images
        #
        self.blivet.do_it()

    def setUp(self):
        """ Do any setup required prior to running a test. """
        self.blivet = Blivet()

        self.addCleanup(self._clean_up)
        self.set_up_storage()

    def _clean_up(self):
        """ Clean up any resources that may have been set up for a test. """
        self.blivet.reset()

        # XXX The only reason for this may be lvmetad
        for disk in self.blivet.disks:
            self.blivet.recursive_remove(disk)

        try:
            self.blivet.do_it()
        except Exception:
            self.blivet.reset()
            raise
Exemplo n.º 2
0
class DBusBlivet(DBusObject):
    """ This class provides the main entry point to the Blivet1 service.

        It provides methods for controlling the blivet service and querying its
        state.
    """
    def __init__(self, manager):
        super().__init__(manager)
        self._blivet = Blivet()
        self._id = ObjectID().id
        self._manager.add_object(self)
        self._set_up_callbacks()

    def _set_up_callbacks(self):
        callbacks.device_added.add(self._device_added)
        callbacks.device_removed.add(self._device_removed)
        callbacks.format_added.add(self._format_added)
        callbacks.format_removed.add(self._format_removed)
        callbacks.action_added.add(self._action_added)
        callbacks.action_removed.add(self._action_removed)
        callbacks.action_executed.add(self._action_executed)

    @property
    def id(self):
        return self._id

    @property
    def object_path(self):
        return BLIVET_OBJECT_PATH

    @property
    def interface(self):
        return BLIVET_INTERFACE

    @property
    def properties(self):
        props = {"Devices": self.ListDevices()}
        return props

    def _device_removed(self, device, keep=True):
        """ Update ObjectManager interface after a device is removed. """
        # Make sure the format gets removed in case the device was removed w/o
        # removing the format first.
        removed_fmt = self._manager.get_object_by_id(device.format.id)
        if removed_fmt and removed_fmt.present:
            self._format_removed(device, device.format, keep=keep)
        elif removed_fmt and not keep:
            self._format_removed(device, device.format, keep=False)

        removed = self._manager.get_object_by_id(device.id)
        self._manager.remove_object(removed)
        if keep:
            removed.present = False
            self._manager.add_object(removed)
        else:
            removed.remove_from_connection()

    def _device_added(self, device):
        """ Update ObjectManager interface after a device is added. """
        added = self._manager.get_object_by_id(device.id)
        if added:
            # This device was previously removed. Restore it.
            added.present = True
        else:
            added = DBusDevice(device, self._manager)

        self._manager.add_object(added)

    def _format_removed(self, device, fmt, keep=True):  # pylint: disable=unused-argument
        removed = self._manager.get_object_by_id(fmt.id)
        if removed is None:
            return

        # We have to remove the object either way since its path will change.
        self._manager.remove_object(removed)
        if keep:
            removed.present = False
            self._manager.add_object(removed)
        else:
            removed.remove_from_connection()

    def _format_added(self, device, fmt):  # pylint: disable=unused-argument
        added = self._manager.get_object_by_id(fmt.id)
        if added:
            # This format was previously removed. Restore it.
            added.present = True
        else:
            added = DBusFormat(fmt, self._manager)

        self._manager.add_object(added)

    def _action_removed(self, action):
        removed = self._manager.get_object_by_id(action.id)
        self._manager.remove_object(removed)
        removed.remove_from_connection()

    def _action_added(self, action):
        added = DBusAction(action, self._manager)
        self._manager.add_object(added)

    def _action_executed(self, action):
        if action.is_destroy:
            if action.is_device:
                self._device_removed(action.device, keep=False)
            elif action.is_format:
                self._format_removed(action.device, action.format, keep=False)

        self._action_removed(action)

    def _list_dbus_devices(self, removed=False):
        dbus_devices = (d for d in self._manager.objects if isinstance(d, DBusDevice))
        return [d for d in dbus_devices if removed or d.present]

    def _get_device_by_object_path(self, object_path, removed=False):
        """ Return the StorageDevice corresponding to an object path. """
        dbus_device = self._manager.get_object_by_path(object_path)
        if dbus_device is None or not isinstance(dbus_device, DBusDevice):
            raise dbus.exceptions.DBusException('%s.DeviceNotFound' % BUS_NAME,
                                                'No device found with object path "%s".'
                                                % object_path)

        if not dbus_device.present and not removed:
            raise dbus.exceptions.DBusException('%s.DeviceNotFound' % BUS_NAME,
                                                'Device with object path "%s" has already been '
                                                'removed.' % object_path)

        return dbus_device._device

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE)
    def Reset(self):
        """ Reset the Blivet instance and populate the device tree. """
        old_devices = self._blivet.devices[:]
        for removed in old_devices:
            self._device_removed(device=removed, keep=False)

        self._blivet.reset()

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE)
    def Exit(self):
        """ Stop the blivet service. """
        sys.exit(0)

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE, out_signature='ao')
    def ListDevices(self):
        """ Return a list of strings describing the devices in this system. """
        object_paths = sorted_object_paths_from_list(self._list_dbus_devices())
        return dbus.Array(object_paths, signature='o')

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE, in_signature='s', out_signature='o')
    def ResolveDevice(self, spec):
        """ Return a string describing the device the given specifier resolves to. """
        device = self._blivet.devicetree.resolve_device(spec)
        if device is None:
            raise dbus.exceptions.DBusException('%s.DeviceLookupFailed' % BUS_NAME,
                                                'No device was found that matches the device '
                                                'descriptor "%s".' % spec)

        return self._manager.get_object_by_id(device.id).object_path

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE, in_signature='o')
    def RemoveDevice(self, object_path):
        """ Remove a device and all devices built on it. """
        device = self._get_device_by_object_path(object_path)
        self._blivet.devicetree.recursive_remove(device)

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE, in_signature='o')
    def InitializeDisk(self, object_path):
        """ Clear a disk and create a disklabel on it. """
        self.RemoveDevice(object_path)
        device = self._get_device_by_object_path(object_path)
        self._blivet.initialize_disk(device)

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE)
    def Commit(self):
        """ Commit pending changes to disk. """
        try:
            self._blivet.do_it()
        except StorageError as e:
            raise dbus.exceptions.DBusException('%s.%s' % (BUS_NAME, e.__class__.__name__),
                                                "An error occured while committing the "
                                                "changes to disk: %s" % str(e))
Exemplo n.º 3
0
class VMBackedTestCase(unittest.TestCase):

    """ A class to encapsulate testing of blivet using block devices.

        The basic idea is you create some scratch block devices and then run
        some test code on them.

        :attr:`~.ImageBackedTestCase.disks` defines the set of disk images.

        :meth:`~.ImageBackedTestCase._set_up_storage` is where you specify the
        initial layout of the disks. It will be written to the disk images in
        :meth:`~.ImageBackedTestCase.set_up_storage`.

        You then write test methods as usual that use the disk images, which
        will be cleaned up and removed when each test method finishes.
    """

    initialize_disks = True  # Whether or not to create a disklabel on the disks.

    def set_up_disks(self):
        """ Create disk image files to build the test's storage on.

            If you are actually creating the disk image files here don't forget
            to set the initialize_disks flag so they get a fresh disklabel when
            clear_partitions gets called from create_storage later.
        """

    def _set_up_storage(self):
        """ Schedule creation of storage devices on the disk images.

            .. note::

                The disk images should already be in a populated devicetree.

        """

    def set_up_storage(self):
        """ Create a device stack on top of disk images for this test to run on.

            This will write the configuration to whatever disk images are
            defined in set_up_disks.
        """
        #
        # create disk images
        #
        self.set_up_disks()

        #
        # populate the devicetree
        #
        self.blivet.reset()

        if self.initialize_disks:
            for disk in self.blivet.disks:
                self.blivet.initialize_disk(disk)

        #
        # create the rest of the stack
        #
        self._set_up_storage()

        #
        # write configuration to disk images
        #
        self.blivet.do_it()

    def setUp(self):
        """ Do any setup required prior to running a test. """
        self.blivet = Blivet()

        self.addCleanup(self._clean_up)
        self.set_up_storage()

    def _clean_up(self):
        """ Clean up any resources that may have been set up for a test. """
        self.blivet.reset()

        # XXX The only reason for this may be lvmetad
        for disk in self.blivet.disks:
            self.blivet.recursive_remove(disk)

        try:
            self.blivet.do_it()
        except Exception:
            self.blivet.reset()
            raise
Exemplo n.º 4
0
class DBusBlivet(DBusObject):
    """ This class provides the main entry point to the Blivet1 service.

        It provides methods for controlling the blivet service and querying its
        state.
    """
    def __init__(self, manager):
        super().__init__(manager)
        self._blivet = Blivet()
        self._id = ObjectID().id
        self._manager.add_object(self)
        self._set_up_callbacks()

    def _set_up_callbacks(self):
        callbacks.device_added.add(self._device_added)
        callbacks.device_removed.add(self._device_removed)
        callbacks.format_added.add(self._format_added)
        callbacks.format_removed.add(self._format_removed)
        callbacks.action_added.add(self._action_added)
        callbacks.action_removed.add(self._action_removed)
        callbacks.action_executed.add(self._action_executed)

    @property
    def id(self):
        return self._id

    @property
    def object_path(self):
        return BLIVET_OBJECT_PATH

    @property
    def interface(self):
        return BLIVET_INTERFACE

    @property
    def properties(self):
        props = {
            "Devices": self.ListDevices(),
            "DEVICE_TYPE_LVM": DEVICE_TYPE_LVM,
            "DEVICE_TYPE_LVM_THINP": DEVICE_TYPE_LVM_THINP,
            "DEVICE_TYPE_PARTITION": DEVICE_TYPE_PARTITION,
            "DEVICE_TYPE_MD": DEVICE_TYPE_MD,
            "DEVICE_TYPE_BTRFS": DEVICE_TYPE_BTRFS
        }
        return props

    def _device_removed(self, device, keep=True):
        """ Update ObjectManager interface after a device is removed. """
        # Make sure the format gets removed in case the device was removed w/o
        # removing the format first.
        removed_fmt = self._manager.get_object_by_id(device.format.id)
        if removed_fmt and removed_fmt.present:
            self._format_removed(device, device.format, keep=keep)
        elif removed_fmt and not keep:
            self._format_removed(device, device.format, keep=False)

        removed = self._manager.get_object_by_id(device.id)
        self._manager.remove_object(removed)
        if keep:
            removed.present = False
            self._manager.add_object(removed)

    def _device_added(self, device):
        """ Update ObjectManager interface after a device is added. """
        added = self._manager.get_object_by_id(device.id)
        if added:
            # This device was previously removed. Restore it.
            added.present = True
        else:
            added = DBusDevice(device, self._manager)

        self._manager.add_object(added)

    def _format_removed(self, device, fmt, keep=True):  # pylint: disable=unused-argument
        removed = self._manager.get_object_by_id(fmt.id)
        if removed is None:
            return

        # We have to remove the object either way since its path will change.
        self._manager.remove_object(removed)
        if keep:
            removed.present = False
            self._manager.add_object(removed)

    def _format_added(self, device, fmt):  # pylint: disable=unused-argument
        added = self._manager.get_object_by_id(fmt.id)
        if added:
            # This format was previously removed. Restore it.
            added.present = True
        else:
            added = DBusFormat(fmt, self._manager)

        self._manager.add_object(added)

    def _action_removed(self, action):
        removed = self._manager.get_object_by_id(action.id)
        self._manager.remove_object(removed)

    def _action_added(self, action):
        added = DBusAction(action, self._manager)
        self._manager.add_object(added)

    def _action_executed(self, action):
        if action.is_destroy:
            if action.is_device:
                self._device_removed(action.device, keep=False)
            elif action.is_format:
                self._format_removed(action.device, action.format, keep=False)

        self._action_removed(action)

    def _list_dbus_devices(self, removed=False):
        dbus_devices = (d for d in self._manager.objects
                        if isinstance(d, DBusDevice))
        return [d for d in dbus_devices if removed or d.present]

    def _get_device_by_object_path(self, object_path, removed=False):
        """ Return the StorageDevice corresponding to an object path. """
        dbus_device = self._manager.get_object_by_path(object_path)
        if dbus_device is None or not isinstance(dbus_device, DBusDevice):
            raise dbus.exceptions.DBusException(
                '%s.DeviceNotFound' % BUS_NAME,
                'No device found with object path "%s".' % object_path)

        if not dbus_device.present and not removed:
            raise dbus.exceptions.DBusException(
                '%s.DeviceNotFound' % BUS_NAME,
                'Device with object path "%s" has already been '
                'removed.' % object_path)

        return dbus_device._device

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE)
    def Reset(self):
        """ Reset the Blivet instance and populate the device tree. """
        old_devices = self._blivet.devices[:]
        for removed in old_devices:
            self._device_removed(device=removed, keep=False)

        for action in self._blivet.devicetree.actions:
            self._action_removed(action)

        self._blivet.reset()

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE)
    def Exit(self):
        """ Stop the blivet service. """
        sys.exit(0)

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE, out_signature='ao')
    def ListDevices(self):
        """ Return a list of strings describing the devices in this system. """
        object_paths = sorted_object_paths_from_list(self._list_dbus_devices())
        return dbus.Array(object_paths, signature='o')

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE,
                         in_signature='s',
                         out_signature='o')
    def ResolveDevice(self, spec):
        """ Return a string describing the device the given specifier resolves to. """
        device = self._blivet.devicetree.resolve_device(spec)
        if device is None:
            raise dbus.exceptions.DBusException(
                '%s.DeviceLookupFailed' % BUS_NAME,
                'No device was found that matches the device '
                'descriptor "%s".' % spec)

        return self._manager.get_object_by_id(device.id).object_path

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE, in_signature='o')
    def RemoveDevice(self, object_path):
        """ Remove a device and all devices built on it. """
        device = self._get_device_by_object_path(object_path)
        self._blivet.devicetree.recursive_remove(device)

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE, in_signature='o')
    def InitializeDisk(self, object_path):
        """ Clear a disk and create a disklabel on it. """
        self.RemoveDevice(object_path)
        device = self._get_device_by_object_path(object_path)
        self._blivet.initialize_disk(device)

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE)
    def Commit(self):
        """ Commit pending changes to disk. """
        try:
            self._blivet.do_it()
        except StorageError as e:
            raise dbus.exceptions.DBusException(
                '%s.%s' % (BUS_NAME, e.__class__.__name__),
                "An error occured while committing the "
                "changes to disk: %s" % str(e))

    @dbus.service.method(dbus_interface=BLIVET_INTERFACE,
                         in_signature='ita{sv}',
                         out_signature='o')
    def Factory(self, device_type, size, kwargs):
        disks = [
            self._get_device_by_object_path(p)
            for p in kwargs.pop("disks", [])
        ]
        kwargs["disks"] = disks

        dbus_device = kwargs.pop("device", None)
        if dbus_device:
            device = self._get_device_by_object_path(dbus_device)
            kwargs["device"] = device

        try:
            device = self._blivet.factory_device(device_type, Size(size),
                                                 **kwargs)
        except StorageError as e:
            raise dbus.exceptions.DBusException(
                '%s.%s' % (BUS_NAME, e.__class__.__name__),
                "An error occured while configuring the "
                "device: %s" % str(e))

        if device is None:
            object_path = '/'
        else:
            object_path = self._manager.get_object_by_id(device.id).object_path

        return object_path
Exemplo n.º 5
0
class ImageBackedTestCase(unittest.TestCase):
    """ A class to encapsulate testing of blivet using block devices.

        The basic idea is you create some scratch block devices and then run
        some test code on them.

        :attr:`~.ImageBackedTestCase.disks` defines the set of disk images.

        :meth:`~.ImageBackedTestCase._set_up_storage` is where you specify the
        initial layout of the disks. It will be written to the disk images in
        :meth:`~.ImageBackedTestCase.set_up_storage`.

        You then write test methods as usual that use the disk images, which
        will be cleaned up and removed when each test method finishes.
    """

    initialize_disks = True
    """ Whether or not to create a disklabel on the disks. """

    disks = {"disk1": Size("2 GiB"), "disk2": Size("2 GiB")}
    """ The names and sizes of the disk images to create/use. """
    def set_up_disks(self):
        """ Create disk image files to build the test's storage on.

            If you are actually creating the disk image files here don't forget
            to set the initialize_disks flag so they get a fresh disklabel when
            clear_partitions gets called from create_storage later.
        """
        for (name, size) in iter(self.disks.items()):
            path = util.create_sparse_tempfile(name, size)
            self.blivet.disk_images[name] = path

        #
        # set up the disk images with a disklabel
        #
        self.blivet.config.initialize_disks = self.initialize_disks

    def _set_up_storage(self):
        """ Schedule creation of storage devices on the disk images.

            .. note::

                The disk images should already be in a populated devicetree.

        """
        pass

    def set_up_storage(self):
        """ Create a device stack on top of disk images for this test to run on.

            This will write the configuration to whatever disk images are
            defined in set_up_disks.
        """
        #
        # create disk images
        #
        self.set_up_disks()

        #
        # populate the devicetree
        #
        self.blivet.reset()

        #
        # clear and/or initialize disks as specified in set_up_disks
        #
        self.blivet.clear_partitions()

        #
        # create the rest of the stack
        #
        self._set_up_storage()

        #
        # write configuration to disk images
        #
        self.blivet.do_it()

    def setUp(self):
        """ Do any setup required prior to running a test. """
        flags.image_install = True
        self.blivet = Blivet()

        self.addCleanup(self._clean_up)
        self.set_up_storage()

    def _clean_up(self):
        """ Clean up any resources that may have been set up for a test. """

        # XXX The only reason for this may be lvmetad
        for disk in self.blivet.disks:
            self.blivet.recursive_remove(disk)

        try:
            self.blivet.do_it()
        except Exception:
            self.blivet.reset()
            raise

        self.blivet.reset()
        self.blivet.devicetree.teardown_disk_images()
        for fn in self.blivet.disk_images.values():
            if os.path.exists(fn):
                os.unlink(fn)

        flags.image_install = False
Exemplo n.º 6
0
class ImageBackedTestCase(unittest.TestCase):

    """ A class to encapsulate testing of blivet using block devices.

        The basic idea is you create some scratch block devices and then run
        some test code on them.

        :attr:`~.ImageBackedTestCase.disks` defines the set of disk images.

        :meth:`~.ImageBackedTestCase._set_up_storage` is where you specify the
        initial layout of the disks. It will be written to the disk images in
        :meth:`~.ImageBackedTestCase.set_up_storage`.

        You then write test methods as usual that use the disk images, which
        will be cleaned up and removed when each test method finishes.
    """

    initialize_disks = True
    """ Whether or not to create a disklabel on the disks. """

    disks = {"disk1": Size("2 GiB"),
             "disk2": Size("2 GiB")}
    """ The names and sizes of the disk images to create/use. """

    def set_up_disks(self):
        """ Create disk image files to build the test's storage on.

            If you are actually creating the disk image files here don't forget
            to set the initialize_disks flag so they get a fresh disklabel when
            clear_partitions gets called from create_storage later.
        """
        for (name, size) in iter(self.disks.items()):
            path = util.create_sparse_tempfile(name, size)
            self.blivet.disk_images[name] = path

        #
        # set up the disk images with a disklabel
        #
        self.blivet.config.initialize_disks = self.initialize_disks

    def _set_up_storage(self):
        """ Schedule creation of storage devices on the disk images.

            .. note::

                The disk images should already be in a populated devicetree.

        """

    def set_up_storage(self):
        """ Create a device stack on top of disk images for this test to run on.

            This will write the configuration to whatever disk images are
            defined in set_up_disks.
        """
        #
        # create disk images
        #
        self.set_up_disks()

        #
        # populate the devicetree
        #
        self.blivet.reset()

        #
        # clear and/or initialize disks as specified in set_up_disks
        #
        self.blivet.clear_partitions()

        #
        # create the rest of the stack
        #
        self._set_up_storage()

        #
        # write configuration to disk images
        #
        self.blivet.do_it()

    def setUp(self):
        """ Do any setup required prior to running a test. """
        self.blivet = Blivet()

        self.addCleanup(self._clean_up)
        self.set_up_storage()

    def _clean_up(self):
        """ Clean up any resources that may have been set up for a test. """

        # XXX The only reason for this may be lvmetad
        for disk in self.blivet.disks:
            self.blivet.recursive_remove(disk)

        try:
            self.blivet.do_it()
        except Exception:
            self.blivet.reset()
            raise

        self.blivet.reset()
        self.blivet.devicetree.teardown_disk_images()
        for fn in self.blivet.disk_images.values():
            if os.path.exists(fn):
                os.unlink(fn)