YaST2 is a modular system for Linux installation and system administration. The design goals include:
Flexibility
Extensibility
Maintainability
Network transparency
support administration of remote hosts or virtual machines on mainframes, machines without CD/DVD drives, rack-mounted machines
User interface independence
must run in graphical and text-only environments and serial consoles
Cover the whole range from novice users to expert system administrators
To achieve the above design goals, YaST2 is split up into a number of components for each individual task:
There is the core engine and to run scripts written in YCP (YaST2's own scripting language), Perl or (in future releases) other scripting languages.
The engine and scripts together form a YaST2 Module for the user.
Even though in most scenarios there is only one single machine, it is important to distinguish between the installation source machine and the installation target machine:
The installation source machine is the machine that holds the installation media - usually CDs or DVDs - and a mini-Linux called "inst-sys" that is copied from one of those installation media to that machine's RAM disk to have a basic operating system to work with on a "bare metal" machine (a machine that doesn't have an operating system installed yet). Most of that inst-sys is read-only, there is only limited disk space for temporary files, and since everything runs from a RAM disk the writable part of it is very volatile.
The installaton target on the other hand is the machine that is to be installed or administered. That may be the same machine as the installation source machine (in fact, this is very common for PC installation or administration tasks), but it might as well be two distinct machines - a virtual machine on a mainframe computer or a remote rack-mounted machine without any display adapter or CD/DVD drives.
All communication with the installation target is handled via the System Configuration Repository (SCR) to guarantee the network abstraction design goal. This is much easier said than done, however: YaST2 module developers always have to keep in mind that it is strictly forbidden to access system files (or any other system resources, for that matter) directly, even if there may be very convenient CPAN Perl modules to do that. Rather, SCR is to be used instead - always. Otherwise everything might run fine if installation source and target are the same machine, but break horribly if they are not.
SCR in itself is also modularized: All calls are handled by "agents" that each know how to handle a particular configuration "path" like "/etc/fstab" or "/etc/passwd". That may be a simple file, but it may also be a directory hierarchy like "probe" - this particular agent handles all kinds of hardware probing, from mouse and display adapters to storage device controllers (like SCSI or IDE controllers), disks attached to each individual controller or partitions on those disks. Paths are denoted like ".etc.fstab" for SCR. YCP even has a special data type "path" for just this case (a special kind of string with some special operations).
SCR agents handle no more than three calls:
SCR::Read()
SCR::Write()
SCR::Execute()
The first argument is always the path to handle, but there may be any number of additional parameters, depending on the agent.
While Read() and Write() are obvious, Execute() may not be: This is intended for some kinds of agents that actually run a program on the installation target. In particular, the ".target.bash" agent does that - it runs a "bash" shell on the target machine and accepts a shell command as an argument. This is the tool of choice for tasks such as starting or stopping system services on the target machine - and again, the distinction between installation source and installaton target machine becomes very important: You want to start or stop the service on the (possibly remote) target machine, not on the machine that happens to hold the installation media.
SCR agents can easily added when needed. There are frameworks available to write SCR agents in C++, in Perl, or as Bash shell scripts as well as several ready-made parsers for different file formats like the ".ini" file parser that can handle files with "key = value" pairs or the "anyagent" that generalizes that concept even more using regular expressions. Those parsers return YCP lists and maps ready for further processing.
Typically, a YaST2 module for a specific installation or administration task includes a set of YCP or Perl scripts as well as some SCR agents to handle its particular configuration files.
Given the wide variety of machines that can possibly be handled with YaST2, it is important to keep the user interface (UI) abstraction in mind - very much like the SCR, the UI does not necessarily run on the installation target machine. It doesn't even need to run on the same machine as the WFM.
The UI provides dialogs with "widgets" - user interface elements such as input fields, selection lists or buttons. It is transparent to the calling application if those widgets are part of a graphical toolkit such as Qt, or text based (using the NCurses library) or something completely else. An input field for example only guarantees that the user can enter and edit some value with it. A button only provides means to notify the application when the user activated it - by mouse click (if the UI supports using pointing devices such as a mouse), by key press or however else.
The UI has a small number of built-in functions - for example:
UI::OpenDialog() accepts a widget hierarchy as an argument and opens a dialog with those widgets
UI::CloseDialog() closes a dialog
UI::QueryWidget() returns a widget's property such as the current value of an input field or selection box
UI::ChangeWidget() changes a widget's property
UI::UserInput() waits until the user has taken some action such as activate a button - after which the application can call UI::QueryWidget() for each widget in the dialog to get the current values the user entered. The application does not have to handle every key press in each input field directly - the widgets are self-sufficient to a large degree.
There is virtually no low-level control for the widgets - nor is it necessary or even desired to have that. You don't specify a button's width or height - you specify its label to be "Continue", for example, and it will adapt its dimensions accordingly. If desired, more specific layout constraints can be specified: For example, buttons can be arranged in a row with equal width each. The UI will resize them as needed, giving them additional margins if necessary.
The existing UIs provide another layer of network abstraction: The graphical UI uses the Qt toolkit which is based on the X Window System's Xlib which in turn uses the X protocol (usually) running on top of TCP/IP. X Terminals can be used as well as a Linux console (that may be the installation source machine or the installation target machine or another machine connected via the network) running the X Window System or even X servers running on top of other operating systems.
The NCurses (text based) UI requires no more than a shell session - on a text terminal (serial console or other), on a Linux console, in an XTerm session, via ssh or whatever.
Currently, there is no web UI, but YaST2's concepts would easily allow for that if it proves useful or necessary.
The component broker is the central piece of YaST. It acts as a dispatcher for all other components: When a (YCP, Perl or whatever) script calls a function, the broker determines what component handles that function call based on the respective namespace identifier. It is transparent to the caller what programming language a function is written in; the component broker handles that kind of dispatching. The caller only needs to know the function name, its namespace and (or course) the required parameters.
For example, calls like UI::OpenDialog() go to the UI (the user interface), SCR::Read() to the SCR (the system configuration repository). Even scripts can provide namespaces via modules in YCP or Perl.
All communication between the different parts of YaST core is done via a predefined set of YCP data types - simple data types like string, integer, boolean etc., but also compound data types like maps (key / value pairs, also known as "hashes" in other programming languages) or lists (like arrays or vectors in other programming languages). For complex data structures, maps, lists and simple data types can be nested to any degree.
The core-engine of YaST consists of some binary components (modules) that are interconnected via YaST-specific protocols. There are clients as well as servers that are responsible for specific tasks that may have to be accomplished during a YaST-session. According to the well-known client-server-paradigm often used in software technology, YaST-servers are program modules that passively await connections from certain clients to process their requests. Clients on the other hand are active components that send requests to the servers thereby initiating certain actions.
For example the SCR and the UI act as server components that process client-requests on demand. An example for a client module is the stdio-component that can be used to connect the YaST-internal communication with a terminal.
Because this architectural speciality is meant to be used only by the YaST core developers to establish and maintain the low-level machinery we will not go into more detail here. Instead we will focus on the advocated method of extending YaST at the “open end” by creating YCP-modules.