Frequently Asked Questions
- 1. General / Unsorted
-
- 1.1. How to comment functions and variables
- 1.2. How to read and write text files in YaST?
- 1.3. How to read and write sysconfig values?
- 1.4. How to run external programs?
- 1.5. Where are proposal screens handled during 2nd stage of
installation?
- 1.6. Where the YaST2 logs can be found?
- 1.7. How is YaST2 logging done?
- 1.8. How to mark any text for the translation?
- 1.9. What kinds of VALIDATION code has been implemented in modules?
- 1.10. Are there some good examples of the use of Wizard? Any documentation?
- 1.11. What is the semantics of Wizard::SetDesktopIcon ("proxy") ?
- 1.12. What is the semantics of Wizard::CreateDialog() ?
- 1.13. What is the meaning of YCP files generated by y2tool?
- 1.14. Has anyone created a YaST mode for EMACS?
- 1.15. How to add a user using a script?
- 1.16. Could be any map seen as a tree?
- 1.17. How to create a new YaST module
- 2. Testing
-
- 2.1. How to test the YCP code?
- 2.2. How to test the SCR agent?
- 2.3. How to start and stop services?
- 2.4. How to test the first stage installation (before reboot)?
- 2.5. How to test the second stage installation (after reboot)?
- 2.6. How to test the installation proposals?
- 2.7. How to test YaPI and PerlAPI functions?
- 2.8. How to test the AutoYaST?
- 2.9. How to test the AutoInstallation?
1. General / Unsorted | - 1.1. How to comment functions and variables
- 1.2. How to read and write text files in YaST?
- 1.3. How to read and write sysconfig values?
- 1.4. How to run external programs?
- 1.5. Where are proposal screens handled during 2nd stage of
installation?
- 1.6. Where the YaST2 logs can be found?
- 1.7. How is YaST2 logging done?
- 1.8. How to mark any text for the translation?
- 1.9. What kinds of VALIDATION code has been implemented in modules?
- 1.10. Are there some good examples of the use of Wizard? Any documentation?
- 1.11. What is the semantics of Wizard::SetDesktopIcon ("proxy") ?
- 1.12. What is the semantics of Wizard::CreateDialog() ?
- 1.13. What is the meaning of YCP files generated by y2tool?
- 1.14. Has anyone created a YaST mode for EMACS?
- 1.15. How to add a user using a script?
- 1.16. Could be any map seen as a tree?
- 1.17. How to create a new YaST module
|
1.1. | How to comment functions and variables |
|
This section describes how to comment functions for other
YaST tools to let them generate documentation automatically.
Documentation is generated by script
/usr/lib/YaST2/bin/ycpdoc which can be found
in the yast2-devtools package. See more detailed
information by typing
perldoc /usr/lib/YaST2/bin/ycpdoc . More examples
can be found in the yast2-devtools package or
in the /usr/share/doc/packages/yast2-devtools/ycpdoc/example/
directory.
This is the exemplary file header
/**
* File: modules/AnyFile.ycp
* Package: Fork and Knife Configuration
* Summary: Interface manipulation (/etc/sysconfig/fork and /etc/sysconfig/knife)
* Authors: John The Fish <johnthefish@yahoo.com>
*
* $Id: AnyFile.ycp 43423 2005-12-24 16:14:12Z fish $
*
* Imagine that this is a long description text.
*/
ycpdoc recognizes comments when they are marked with special syntax
/**
* some description
* can be multiline
*/
Exemplary function comment
/**
* @short Returns names of network devices
* @descr This is a multi-line
* function description
*
* @param boolean configured whether function should return configured
* or unconfigured network devices
* @param string any_string_param just some second function parameter
* @return list <string> of network device names
*
* @see GetAllNetworkInterfaceNames1
* @see GetAllNetworkInterfaceNames2
* @example
* // Returns configured devices
* GetAllNetworkDeviceNames(true, "this is a string")
*
* // Returns unconfigured devices
* GetAllNetworkDeviceNames(false, "this is another string")
*/
global list <string> GetAllNetworkDeviceNames (boolean configured, string any_string_param) {
// ...
return [ "Network Device Name 1", "Network Device Name 2" ];
}
Exemplary variable descriptions
/**
* This variable says whether the example is nice or not
*/
global boolean nice_example = true;
/**
* Local variable for caching found keys/values
*/
map <string, string> closer_defined_map = $[ "key1" : "value", "key2" : "any string" ];
// This variable will not be documented
list <string> xyz = [ "string 1", "string 2", "string 3" ];
|
1.2. | How to read and write text files in YaST? |
|
Use .target.string path of 'system agent' to
manipulate with the text files.
The Read function returns the whole contents as a one
string, with the write variant you can rewrite the file.
/**
* Example of using SCR/.target.string
*/
{
import "SCR";
string contents = (string) SCR::Read (.target.string, "/some/file");
if (contents == nil)
y2error("filename does not exist");
boolean success = SCR::Write (.target.string,"/some/file", contents);
}
Documentation of system agent can be found at
/usr/share/doc/packages/yast2-core/agent-system
Check for existing SCR agents for various configuration files.
If you want to read/edit/write known config file, it is
very likely that SCR agent for this file already exists. The
easy way to find this out is grep the files under
/usr/share/YaST2/scrconf/ directory
for the file name.
If you want to manipulate with a file contents
(e.g. delete or rewrite some line) it is possible to use
AsciiFile module, which describes the file
by the map.
map file = $[];
AsciiFile::ReadFile (file, "/tmp/myfile");
// now you can check the 'file' map manually
// or using AsciiFile interface ...
AsciiFile::RewriteFile (new_map, "/tmp/myfile");
For more, look directly into /usr/share/YaST2/modules/AsciiFile.ycp .
|
1.3. | How to read and write sysconfig values? |
|
First, you need the scr file which actually
calls an agent that
handles this type of files. In this case it is done using the so
called ini agent which can handle multiple
types of config files, not only ini files.
// read the BASE_CONFIG_DN variable from /etc/sysconfig/ldap
string base_config_dn = SCR::Read (.sysconfig.ldap.BASE_CONFIG_DN);
// ... and save the new value
SCR::Write (.sysconfig.ldap.BASE_CONFIG_DN, new_dn);
For documentation, see
/usr/share/doc/packages/yast2-core/agent-ini/ini.html
|
1.4. | How to run external programs? |
|
Use 'system agent' documented in
/usr/share/doc/packages/yast2-core/agent-system/ .
/**
* Example of using .target.bash
*/
{
import "SCR";
integer ret = (integer) SCR::Execute (.target.bash, "/bin/touch /tmp/file", $[]);
// System environment variables which will be accessible in the
// Execute() command
map environment = $[
"FILE":"/somedir/somefile"
];
string command = "/bin/touch $FILE";
map output = (map) SCR::Execute (.target.bash_output, command, environment);
}
Using .target.bash path you can run bash
command, defined by the
string parameter. The last parameter can be used to give initial
environment definitions to the target. The keys have to be
strings, the values can be of any type. The return value is an
integer with the exitcode. If you use
.target.bash_output path, the return value
will be the map:
$[
"exit" : <integer>, //exitcode from shell script
"stdout" : <string>, //stdout of the command
"stderr" : <string> //stderr of the command
]
|
1.5. | Where are proposal screens handled during 2nd stage of
installation? |
|
For each proposal the control file /var/lib/YaST2/control.xml
contains a
list of clients to be called.
The tag <proposal>
describes the name of the client. Then, the name is suffixed by
_proposal , for instance
proxy_proposal.ycp ,
and such client is started via WFM::Call. The required
action is done by a command line argument. Each proposal client
has to implement the following arguments:
-
MakeProposal - prepare a proposal, return its summary
-
AskUser - start the GUI for user to manually modify the proposal
-
Description - return a map for title, entry in the menu button
and your id
-
Write - user accepted the proposal, write it down
For more details see *_proposal.ycp clients in
/usr/share/YaST2/clients/ directory and documentation in
/usr/share/doc/packages/yast2-installation/ .
|
1.6. | Where the YaST2 logs can be found? |
|
Logs are situated in the /var/log/YaST2/ directory. They are
named y2log and from y2log-1 to
y2log-9 , rotated in the size at about 1.1 MB.
|
1.7. | How is YaST2 logging done? |
|
YaST2 loggings are done using y2* built-in functions. This is a simple
program, which should help us with the logging.
/**
* Example for logging
* File: y2logs.ycp
*/
{
y2debug ("debug");
y2milestone ("milestone");
y2warning ("warning");
y2error ("error");
y2security ("security");
y2internal ("internal");
}
-
y2debug is used only for the debugging
information, only for testing because it is not logged during
the normal run of the YaST2. It is usable only for the developer.
-
y2milestone is used for logging some
important information. For instance
Configuration has been changed, saving into the '/etc/any.conf' .
y2milestone("Configuration has been changed, saving into the '%1'",
"/etc/any.conf");
-
y2warning is used to announce that something would go
wrong. For instance when any configured card has been lost after the reboot.
-
y2error is used for major problems. For instance if
YaST2 didn't find what it expected and needed.
-
y2security is not used.
-
y2internal is not used.
And this is the part of the log found in the logfile
/var/log/YaST2/y2log after we have runned
Y2DEBUG=1 yast2 y2logs.ycp , we would not see any
debug information if we would run
yast2 y2logs.ycp only.
2004-09-21 10:04:13 <0> wizard(5964) [YCP] y2logs.ycp:2 debug
2004-09-21 10:04:13 <1> wizard(5964) [YCP] y2logs.ycp:3 milestone
2004-09-21 10:04:13 <2> wizard(5964) [YCP] y2logs.ycp:4 warning
2004-09-21 10:04:13 <3> wizard(5964) [YCP] y2logs.ycp:5 error
2004-09-21 10:04:13 <4> wizard(5964) [YCP] y2logs.ycp:6 security
2004-09-21 10:04:13 <5> wizard(5964) [YCP] y2logs.ycp:7 internal
Format of the log is [year]-[month]-[day] [time] [log-weight] [process-name](PID)
[library] [filename]:[line-number] [message].
y2* built-in functions accepts maximally 9 parameters of variables:
y2milestone("This is the example for %3, %4, %1 and %2",
"1st parameter", "2nd parameter", "3rd parameter", "4th parameter");
Each %[number] is replaced by the corresponding variable.
Parameters can be all types (function, boolean, integer, map ...).
|
1.8. | How to mark any text for the translation? |
|
There are two internal functions for marking the text for the
translation. They are _(string text) (single
underscore) in YCP and __(string text) (double
underscore) in Perl. It is needed to place every single calling
of the function on the separate line because of making
.pot file. Every text marked for translation
should be commented above for the translators.
/**
* Example for marking texts for translations
*/
{
import "Popup";
textdomain "example";
// TRANSLATORS: Checkbox
term checkbox = `CheckBox(`id("use maximum"), _("Use &Maximum"));
string filename = "/etc/this_file_doesn't_exist";
// TRANSLATORS: An error popup message, %1 is the name of the file
Popup::Error(sformat( _("Cannot open the file '%1'"),
filename)
);
boolean expert_mode = true;
string help =
// TRANSLATORS: help text for simple and expert functonality (1/2)
_("<p>This is the help text for the simple functionality</p>") +
(expert_mode == true ?
// TRANSLATORS: help text for expert functionality only (2/2)
_("<p>And this is the help for the additional functionality</p>")
:
""
);
}
|
1.9. | What kinds of VALIDATION code has been implemented in modules? |
|
For simple syntax validation there is a lot of it, but only the
basic ones are grouped together in the yast2.rpm .
Those are:
-
IP::Check(), IP::Check4(), IP::Check6() for IP addresses checking
-
Hostname::Check(), Hostname::CheckDomain(), Hostname::CheckFQ() for Hostnames (DNS)
-
Address::Check(), Address::Check4(), Address::Check6()
for addresses (IP or a hostname)
-
Netmask::Check(), Netmask::Check4(), Netmask::Check6()
for netmasks
-
URL::Check() for URL syntax
For the rest you need to lookup in the corresponding YaST modules.
|
1.10. | Are there some good examples of the use of Wizard? Any documentation?
|
|
See /usr/share/doc/packages/yast2/wizard/examples/ and
/usr/share/doc/packages/yast2-core/libyui/examples/Wizard...
The wizard is controlled by the Wizard YCP module
(import "Wizard" ).
It's documentation is in
/usr/share/YaST2/modules/Wizard.ycp .
|
1.11. | What is the semantics of Wizard::SetDesktopIcon ("proxy") ? |
|
This sets the icon at the left side of the dialog title label
to the one used by the yast2-proxy desktop file.
It is the same as appears in the yast2 control center.
|
1.12. | What is the semantics of Wizard::CreateDialog() ?
|
|
This creates a Wizard Dialog. This is the basic
framework used in YaST screens with help on the left and
the YaST graphics on top. At the bottom there are
usually three buttons, Back ,
Abort and Next .
This is how a workflow is implemented. However, in the
last step of a workflow, naming the rightmost button
"next" isn't appropriate.
Wizard::SetNextButton (`next, Label::FinishButton);
replaces the button caption with "Finish".
In some dialogs you need to hide some default buttons
or to restorem them again.
Wizard::HideBackButton ();
hides the Back button.
Wizard::RestoreAbortButton ();
restores hidden Abort button.
|
1.13. | What is the meaning of YCP files generated by y2tool? |
|
TODO ... more about templates, and devtools
|
1.14. | Has anyone created a YaST mode for EMACS? |
|
TODO
Syntax file for VIM is part of SUSE's vim package.
|
1.15. | How to add a user using a script? |
|
For documentation of whole Users module API, look at
/usr/share/YaST2/modules/YaPI/USERS.pm
Example 1. YCP script
/**
* Simple script for adding new user
* call 'yast2 adduser.ycp <username> <password>
*/
{
import "YaPI::USERS";
// take user name and password from the command line
list args = WFM::Args ();
string uid = args[0]:"";
string passwd = args[1]:"";
map<string,any> config = $[];
map<string,any> data = $[
"uid" : uid,
"userpassword" : passwd
];
string error = YaPI::USERS::UserAdd (config, data);
// the return value is empty string on success
if (error != "")
{
y2error ("add user error: %1", error);
}
}
Example 2. Perl script
#!/usr/bin/perl -w
#
# Simple script for adding new user
# Requires 2 parameters: <username> <password>
#
BEGIN {
push @INC, "/usr/share/YaST2/modules";
}
use YaPI::USERS;
# take user name and password from the command line
my $uid = shift;
my $passwd = shift;
my $config = {};
my $data = {
"uid" => $uid || "",
"userpassword" => $passwd || ""
};
my $error = YaPI::USERS->UserAdd ($config, $data);
# the return value is empty string on success
print "add user error: '$error'\n";
Example 3. Perl script for LDAP user
#!/usr/bin/perl -w
#
# Simple script for adding LDAP user
# Requires 2 parameters: <username> <password>
#
BEGIN {
push @INC, "/usr/share/YaST2/modules";
}
use YaPI::USERS;
# take user name and password from the command line
my $uid = shift;
my $passwd = shift;
my $config = {
"type" => "ldap",
"bind_pw" => "q" # password for LDAP administrator
};
my $data = {
"sn" => $uid || "",
"uid" => $uid || "",
"userpassword" => $passwd || "",
"description" => [ "first", "second" ] # additional LDAP attribute
};
my $error = YaPI::USERS->UserAdd ($config, $data);
# the return value is empty string on success
if ($error) {
print "add user error: '$error'\n";
}
|
1.16. | Could be any map seen as a tree? |
|
Maps which you can find in y2log are not human-readable. You can use
the tree view in UI which is the one you can find in yast2-testsuite
package.
/**
* Example for debugging (browsing) any map in TreeWidget
*/
{
include "devel/debug.ycp"; // including part of yast2-testsuite
map this_map = $[
"list1" : [
$[ "string1" : 555 ], [ "a", "b", "c" ], 1, 2, 3, $[ "b" : 5 ],
$[ "string2" : [ $[ "a" : 1 ], $[ "a" : 22 ], $[ "a" : 333 ] ] ],
],
"list2" : [
$[ "key1" : "value1", "key2" : [ "1", "2", "3" ] ],
[ "string", 1 ], [ 5, "string" ], [ [ 1 ], [ 2 ], [ 3 ] ],
],
];
// Opens UI window with a browsable tree
DEBUG(this_map);
}
As you can see, this is very ugly map. Run
yast2 debug_map.ycp to open the UI
tree and browse the map.
|
1.17. | How to create a new YaST module |
| Use the /usr/bin/y2tool create-new-package .
y2tool is included in the yast2-devtools
package. /usr/bin/y2tool create-new-package -s returns
a list of available skeletons. They are:
To create a new YaST module run: /usr/bin/y2tool
create-new-package -v config module-name "Maintainer Name"
maintainer@email.com |
2. Testing | - 2.1. How to test the YCP code?
- 2.2. How to test the SCR agent?
- 2.3. How to start and stop services?
- 2.4. How to test the first stage installation (before reboot)?
- 2.5. How to test the second stage installation (after reboot)?
- 2.6. How to test the installation proposals?
- 2.7. How to test YaPI and PerlAPI functions?
- 2.8. How to test the AutoYaST?
- 2.9. How to test the AutoInstallation?
|
2.1. | How to test the YCP code? |
|
Use simple command ycpc -E source.ycp . It would
report errors it it would find any.
Attention: files imported and included in the source are got from
the default YaST2 directory /usr/share/YaST2/
first of all other locations.
|
2.2. | How to test the SCR agent? |
|
Use the /usr/lib/YaST2/bin/y2base stdio scr command
which allows you to send commands directly to the SCR. Commands are
`Dir(path) , `Read(path) and
`Write(path) .
|
2.3. | How to start and stop services? |
| Service Manipulation
/**
* Example for service manipulation
*/
{
import "Service";
string service = "squid";
boolean start = Service::Start (service);
boolean stop = Service::Stop (service);
boolean restart = Service::Restart (service);
boolean reload = Service::Reload (service);
}
Service Enabling
/**
* Example handling services in runlevels
*/
{
import "Service";
string service = "cups";
boolean enable = Service::Enable (service);
boolean disable = Service::Disable (service);
// Adjust runleveles for service:
boolean adjust = Service::Adjust (service, "enable");
// Set service to run in selected runlevels:
boolean finetune = Service::Finetune (service, [ 3, 5 ]);
}
Service Information
/**
* Example of getting information about services
*/
{
import "Service";
string service = "sshd";
// Get service info without peeking if service runs:
map info = Service::Info (service);
// Get service info and check if service is running:
map full = Service::FullInfo (service);
// Get service status
integer status = Service::Status (service);
// Returns true if link in /etc/init.d/rc?.d/ exists for this service
boolean enabled = Service::Enabled (service);
}
Documentation can be found in
/usr/share/doc/packages/yast2/runlevel/
|
2.4. | How to test the first stage installation (before reboot)? |
|
...
|
2.5. | How to test the second stage installation (after reboot)? |
|
...
|
2.6. | How to test the installation proposals? |
|
You can use this code to test the `network installation proposal:
/**
* Example of testing network proposal
*/
{
import "Wizard";
import "Mode";
Wizard::CreateDialog ();
Mode::stage = "continue";
WFM::CallFunction ("inst_proposal", [true, true, `network]);
}
Run yast2 network_proposal.ycp to open the UI
with the appropriate installation proposal.
There are more proposals with in more stages. You should find it
in the control.xml file.
-
Proposal: `initial , Stage
initial for the first stage
installation
-
Proposal: `dirinstall , Stage
normal for the installation into
the directory
-
Proposal: `network , Stage
continue for the second stage network
configuration
-
Proposal: `hardware , Stage
continue for the second stage hardware
configuration
|
2.7. | How to test YaPI and PerlAPI functions? |
|
There more methods of testing YaPI and PerlAPI functions. Let me show
you one of them - simple YCP script.
/**
* Example of calling YaIP/PerlAPI functions
*/
{
import "SambaServer";
y2milestone("Export_A: %1", SambaServer::Export());
SambaServer::addShare("NEW1_SHARE", $[ "public" : "yes" ]);
y2milestone("Export_B: %1", SambaServer::Export());
SambaServer::addShare("NEW2_SHARE", $[ "public" : "no" ]);
y2milestone("Export_C: %1", SambaServer::Export());
}
Run this simple script using the yast2 samba.ycp
command and see the log for the result. Here are the interesting
parts of the log:
"shares":[
$["options":[
$["key":"public", "value":"yes"]],
"share":"NEW1_SHARE"
]
] at the "Export_B". "shares":[
$["options":[
$["key":"public", "value":"yes"]],
"share":"NEW1_SHARE"
],
$["options":[
$["key":"public", "value":"no"]],
"share":"NEW2_SHARE"
]
] at the "Export_C".
This is the PerlAPI implementation of the same functionality:
#! /usr/bin/perl -w
# Example of using YaPI/PerlAPI in Perl
use strict;
use Data::Dumper;
use ycp;
use YaST::YCP qw(sformat);
YaST::YCP::Import ("SambaServer");
y2milestone("Export_A: ".Dumper(SambaServer->Export()));
SambaServer->addShare("NEW1_SHARE", { "public" => "yes" });
y2milestone("Export_B: ".Dumper(SambaServer->Export()));
SambaServer->addShare("NEW2_SHARE", { "public" => "no" });
y2milestone("Export_C: ".Dumper(SambaServer->Export()));
This is another example of the YaPI testing. It will open
the popup window with an error message.
/**
* Example of Popup
*/
{
import "Popup";
Popup::Error("Exemplary error message");
}
|
2.8. | How to test the AutoYaST? |
|
...
|
2.9. | How to test the AutoInstallation? |
|
...
|
|