yast2-core
|
The YaST2 component model is the foundation of the YaST2 architecture. It is important to understand at least the basic ideas in order to be able to write new Y2 components. It's based upon the following design principles:
|
All components speak a common language and act according to defined protocol. Both the language and the protocol are called YCP (YaST2 communication protocol). One protocol step consists of one of the partners sending exactly one of YCP Values to the other and the other receiving that value. In the next step, the component that just was receiving, is now sending and vice versa. The only exception is, that one of that partners may terminate the session and send a last result message after which - of course - the partner won't send another value.
There are two different kinds of components: server components and client components, which differ in how the control flows.
A server component is one that - once it's initialized - just waits for jobs to do. Another component can send a request and thus pass the control to the server. That does what is neccessary in order to do handle the request and returns an answer. Prominent examples for server components are the user interfaces. In YaST2 they play a passive role. They just wait for a command like "Show me this dialog, wait for the next user input and return me that input". A server component can also use the service of another server component. For example the SCR (System configuration repository) makes use of servers called agents, which realize subtrees of the SCR tree.
A client component is one that controls the flow. It may contain something like an "event loop". In order to do its work, it can use the services of other server components. Client components are sometimes called modules. Examples for modules are the single steps of the YaST2 "Installation Wizard" or the program that calls rpm
to install packages. Other examples could be a module that configures the network setup of a workstation or one, that just sets the IP-number and the hostname of that workstation.
Modules can be hiearchically structured and hand over control to other modules that acomplish sub tasks and are called submodules in this context. An example is the structure of the YaST2 installer. The installation itself is a module. For each of the wizard window steps, it calls a submodule.
There are quite a number of ways how you can implement a component. A component can be:
|
Don't laugh over the last possibility! For debugging this is sometimes very helpful. You can simulate any component by typing to a terminal.
A component that exists as executable program is realized by a process that is created when the component is needed. If a component needs the services of an external program component, it launches a seperate process and starts a communication via two unix pipes, one in each direction.
The data flowing through these pipes is YCP Ascii representation. Each communication side needs a parser to analyse the data and a YCP syntax generater to write data to the pipe. Both can be found in the libycp Library, which can only used from C++ programs.
But the production of YCP code can in many cases very easily be done be printing to stdout, for example with echo
(shell) or printf
(C).
The parsing of YCP code is as bit more tricky. But in many cases you don't need a full featured parser, because you know beforehand what structure the value have that you get. This especially holds for client components, because they can decide, how the output from the server should look like.
If you anyway decide to write your component in C++, it's by far the most conveniant way to use the functionality of libycp and liby2, whose only purpose is excactly to support component implementation.
What you have to do is to subclass at least two classes: Y2ComponentCreator and Y2Component and
Depending on whether you want to implement a server or a client component you have to override different methods. Many examples can be found within the liby2 itself.
One big advantage of writing a component in C++ is, that you can very easily create three external appearances of the component:
The YaST2 installer makes usage of the third variant only. All required components are linked together to y2base
, which is statically linked against liby2 and libycp. The memory usage is reduced as well as the required disk space. Furthermore no creating and parsing of Ascii streams between the components is required. Protocol steps are simple function calls. Even for very large data structures, only one pointer has to be passed.
If you have installed YaST2, you will find some files ending in .ycp
lying around in /lib/YaST2/clients
. These are YCP scripts implementing client components (modules). YCP is not only a protocol, it is also a full features programming language, which is in this case used to implement components. This is very conveniant as the language can directly operate on the protocol values and has some other nice features.
The client scripts are executed by the Workflowmanager, which is an extension to the core YCP language. It implements a couple of builtin functions that allow communication the the system and with other components. Here is a of builtins..
You can be a component yourself :-). Just tell another component to communicate via stdio and speak with it. For example you can launch the component ycp
by typing y2ycp stdio
. Now you can enter YCP expressions and get the evaluation as answer.