Skip to content

Latest commit

 

History

History
162 lines (123 loc) · 7.43 KB

CONTRIBUTING.md

File metadata and controls

162 lines (123 loc) · 7.43 KB

blivet-gui developer documentation

Development

Running from source

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.)

Running the tests

  • 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 or make 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)

Contributing

Branches

  • main is the only "active development" branch, new features should go to this branch

Code style

  • pep8 (pycodestyle) and pylint 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)

Building blocks of blivet-gui

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

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 (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 actions
  • DeviceToolbar (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.

Dialogs

Most of the user interaction is done using dialogs. Some important dialogs include:

Multiprocess Communication

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 using BlivetGUIClient (BlivetGUI class has an instance of it) remote_call method. So for example to get a list of disks you'll need to use self.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.

Proxy

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

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

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.