Skip to content

Instantly share code, notes, and snippets.

@joseivanlopez
Last active April 8, 2022 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joseivanlopez/a7568408a6bf9defcaa7a92faea9654d to your computer and use it in GitHub Desktop.
Save joseivanlopez/a7568408a6bf9defcaa7a92faea9654d to your computer and use it in GitHub Desktop.

D-Installer needs to offer a D-Bus API for bi-directional communication with the client. Sometimes, the backend has to wait until the client provides some information. A typical case is when requesting for a LUKS password meanwhile the storage system is been probed.

Requirements

The minimal requirements for the communication API are:

  • Emit signal when a new question is added
  • Offer a way to get the list of questions
  • Offer a way to get the list of unanswered questions
  • Offer a way to get information from a question (e.g., the UUID the question refers to)
  • Offer a way to answer a question

Note that the info and the answer can vary depending on the question. For example, asking for continuing or not requires a boolean answer, but asking for a password requires a string be provided.

Proposal

D-Installer service exports a tree of objects to manage the questions:

/org/opensuse/DInstaller/Questions1
    /org/opensuse/DInstaller/Questions1/1
    /org/opensuse/DInstaller/Questions1/2
    /org/opensuse/DInstaller/Questions1/3
    ...

The root object /org/opensuse/DInstaller/Questions1 implements an interface to get the paths of the children objects. It would also emit a signal when a new question is asked. This would be easily done by implementing the org.freedesktop.DBus.ObjectManager interface, but ruby-dbus does not support ObjectManager yet.

An interface similar to ObjectManager could be defined as temporary solution. Such an interface would provide only the minimal stuff required for D-Installer.

/org/opensuse/DInstaller/Questions1
    org.freedesktop.DBus.Properties
    org.freedesktop.DBus.ObjectManager (not supported by ruby-dbus yet)
    org.opensuse.DInstaller.Questions1 (simplified version of ObjectManager)
        # Attribute containing path of all questions. A signal would be emitted when the list changes.
        #
        # Output example:
        #   [
        #     "/org/opensuse/DInstaller/Questions1/1",
        #     "/org/opensuse/DInstaller/Questions1/2,
        #     "/org/opensuse/DInstaller/Questions1/3,
        #     "/org/opensuse/DInstaller/Questions1/4"
        #   ]
        All => as

        # Method for getting list of questions pending to answer
        GetPending () => as

D-Installer service exports a new question object everytime a new question is asked. As commented above, different questions can provide and require different information. To overcome this, each question object would implement the set of interfaces it needs.

A question implements at least the org.opensuse.DInstaller.Question1 interface:

/org/opensuse/DInstaller/Questions1/ID
    org.freedesktop.DBus.Properties
    org.opensuse.DInstaller.Question1
        # Method for getting the question text
        #
        # Output example: "Do you want to continue?"
        Text () => s

        # Method to know if the question was answered
        Answered () => b

If a question is expected to be answered, then the D-Bus object implements the org.opensuse.DInstaller.Question.Answer interface:

/org/opensuse/DInstaller/Questions1/ID
    org.freedesktop.DBus.Properties
    org.opensuse.DInstaller.Question1
    org.opensuse.DInstaller.Question.Answer1
        # Answer provided for this question
        #
        # The returned type depends on the the type of answer
        Value => v

To provide an answer, the D-Bus object has to implement the proper answer interface:

/org/opensuse/DInstaller/Questions1/ID
    org.freedesktop.DBus.Properties
    org.opensuse.DInstaller.Question1
    org.opensuse.DInstaller.Question.Answer1
    org.opensuse.DInstaller.Question.Answer.Boolean1
        Set (b)
    org.opensuse.DInstaller.Question.Answer.String1
        Set (s)

For example, a question that expects to be answered with an string would implement the following interfaces:

/org/opensuse/DInstaller/Questions1/ID
    org.freedesktop.DBus.Properties
    org.opensuse.DInstaller.Question1
    org.opensuse.DInstaller.Question.Answer1
    org.opensuse.DInstaller.Question.Answer.String1

Custom Questions

Sometimes, the client needs to obtain information from a question. For example, when a LUKS password is requested, the client needs to know the device and maybe other properties like size, label, etc. For these cases, the D-Bus object could implement extra interfaces to provide such information. For example, a question asking for a LUKS password would implement these interfaces:

/org/opensuse/DInstaller/Questions1/ID
    org.freedesktop.DBus.Properties
    org.opensuse.DInstaller.Question1
    org.opensuse.DInstaller.Question.Answer1
    org.opensuse.DInstaller.Question.Answer.String1
    org.opensuse.DInstaller.Question.LuksPassword1
        Device => s
        UUID => s
        Label => s
        Size => u

Similarly, custom interfaces can be implemented when a question requires to be answered in a specific way. For example, let's say that the client has to answer to the LUKS password question by providing a struct with two values: whether the device should be activated and the password:

/org/opensuse/DInstaller/Questions1/ID
    org.freedesktop.DBus.Properties
    org.opensuse.DInstaller.Question1
    org.opensuse.DInstaller.Question.Answer1
    org.opensuse.DInstaller.Question.LuksPassword1
    org.opensuse.DInstaller.Question.Answer.LuksPassword1
        Set (b, s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment