To run blivet-gui directly from the source without installing it (e.g. to test some changes) clone the repo (or download a release tarball) and from the directory with the source run
PYTHONPATH=. PATH=`pwd`:$PATH blivet-gui
(You still need to install blivet-gui dependencies to be able to run it. See README.md for more information.)
sudo make test
- run both blivet-gui test suites -- "gui" tests and "utils" tests
- it is possible to run these separately
make gui-test
- tests for the gui
- this test suite needs a graphical session (or a "fake" one like Xvfb) to run
sudo make utils-test
- tests for the backend ("utils") part of blivet-gui
- these tests create virtual SCSI drives using the
targetcli
utility, it is necessary to run these with root privileges
make check
- run static code checks (pylint, pep8 and translation canary)
- it is possible to run these separately --
make pep8
,make pylint
ormake canary
sudo make install-requires
- install some additional dependencies needed for tests (uses an ansible playbook, Fedora, Debian and Ubuntu are currently supported by this target)
main
is the only "active development" branch, new features should go to this branch
pep8
(pycodestyle
) andpylint
are used to check the code, see Running the tests- some checks are disabled, e.g. check for maximum line length (try to keep lines under 100 characters but avoid "artificial" line breaks just to keep lines short)
This is just a short summary of blivet-gui code structure/building blocks. See storaged-project.github.io/blivet-gui for complete API documentation.
BlivetUtils
(blivet_utils.py) class provides a higher level API for Blivet library.
It creates the blivet.Blivet
object and all blivet methods are called using this class.
Check Blivet API documentation for more information about blivet and its API.
BlivetGUI
(blivetgui.py) is the main class for the GUI.
There are separate classes for every UI part. These classes create all the necessary
Gtk widgets (or load them from the Glade files) and provide signal handlers and
other helper functions.
Important GUI objects:
ActionsMenu
(actions_menu.py) -- context (right click) menu for user actionsDeviceToolbar
(actions_toolbar.py) -- toolbar with device-related actions (add, edit, remove...)ActionsToolbar
(actions_toolbar.py)-- toolbar with "global" actions (process or clear actions, main menu)ListDevices
(list_devices.py)-- list of "root" devices (disks, volume groups, RAIDs...)ListPartitions
(list_partitions.py) -- list of "child" devices for selected device- Gets list of "child" devices for given device.
- Decides what "actions" (add, delete...) should be allowed based on current selection.
- Displays list of "child" devices using
Gtk.TreeView
.
LogicalView
(visualization/logical_view.py) -- visualization of child devices. These actually are buttons (Gtk.Button
) styled with css (see rectangle.css)PhysicalView
(visualization/physical_view.py) -- visualization of parents for selected devices.
Most GUI objects are created using the Glade designer. See files in data/ui.
Most of the user interaction is done using dialogs. Some important dialogs include:
AddDialog
(dialogs/add_dialog.py) -- a dialog for adding new devicesResizeDialog
(dialogs/edit_dialog.py) -- a dialog for resizing existing devicesSizeArea
(dialogs/size_chooser.py) -- a special widget for size selection used by both add and resize dialog.FormatDialog
(dialogs/edit_dialog.py) -- a dialog for changing format of existing devices
blivet-gui creates two processes -- blivet-gui
for the UI and blivet-gui-daemon
for working with blivet.
Two processes are necessary because blivet needs root privileges to work with storage but it isn't desirable to run GUI applications as root.
Both processes communicate using a socket file.
For most cases, you don't need to worry about this. The only difference is that instead calling methods from
BlivetUtils
, you need to call them by usingBlivetGUIClient
(BlivetGUI
class has an instance of it)remote_call
method. So for example to get a list of disks you'll need to useself.client.remote_call("get_disks")
. It will return a list of objects that you can use in the same way as DiskDevice objects from blivet.
blivet-gui uses pickle to send
objects between the processes. Unfortunately, most blivet objects are not picklable.
To solve this, server and client parts of blivet-gui use "proxy objects" to
exchange unpicklable data. When BlivetGUI
class "asks" for some "information"
that isn't picklable (e.g. using the get_disks
method from BlivetUtils
which
returns list of StorageDevice
objects), BlivetUtilsServer
(communication/server.py) creates a new instance
of the ProxyID
(communication/proxy_utils.py)
object and sends it to the client instead. When client receives it, it creates an instance of
the ClientProxyObject
(communication/client.py)
object and sends it to the BlivetGUI
instead.
ClientProxyObject
has a custom __getattr__
method and has the ProxyID so it
can ask the server for values of attributes that BlivetGUI
asks for.
Thanks to this, BlivetGUI
can work with the blivet object without actually having it.
ProxyDataContainer
(communication/proxy_utils.py)
is a helper class used as a simple picklable container similar to namedtuple
.
BlivetGUIClient
(communication/client.py)
provides support for multiprocess communication for the client part of the blivet-gui.
BlivetGUI
has an instance of the BlivetGUIClient
and uses it to communicate
with the BlivetUtils
via BlivetUtilsServer
.
BlivetGUI
can call BlivetUtils
methods using BlivetGUIClient.remote_call
method.
BlivetUtilsServer
(communication/server.py)
provides support for multiprocess communication for the server part of the blivet-gui.
It's a synchronous socketserver
, it has an instance of BlivetUtils
and processes
tasks from the BlivetGUIClient
.