home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
root
/
usr
/
share
/
YaST2
/
modules
/
Service.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
13KB
|
473 lines
/**
* File: modules/Service.ycp
* Package: yast2
* Summary: Service manipulation
* Authors: Martin Vidner <mvidner@suse.cz>
* Petr Blahos <pblahos@suse.cz>
* Michal Svec <msvec@suse.cz>
* Lukas Ocilka <locilka@suse.cz>
* Flags: Stable
*
* $Id: Service.ycp 31242 2006-06-01 12:59:16Z locilka $
*
* Functions for service (init script) handling used by other modules.
*/
{
module "Service";
textdomain "base";
/***
* Services Manipulation
*/
/**
* @struct service
* One service is described by such map: <pre>
"servicename" : $[
"defstart" : [ "2", "3", "5", ], // Default-Start comment
"defstop" : [ "0", "1", "6", ], // Default-Stop comment
"reqstart" : [ "$network", "portmap" ], // Required-Start comment
"reqstop" : [ "$network", "portmap" ], // Required-Stop comment
"description" : "text...", // Description comment
"start" : [ "3", "5", ], // which runlevels service is really started/stopped in
"stop" : [ "3", "5", ], // read from /etc/init.d/rc?.d/* links
"started" : 0, // return from rcservice status (integer)
"dirty" : false, // was the entry changed?
]</pre>
*/
/**
* Script location
*/
string init_d = "/etc/init.d";
/**
* After a function returns an error, this holds an error message,
* including insserv stderr and possibly containing newlines.
*
* Set by
* checkExists: [Full]Info, Status, Enabled, Adjust, Finetune
*
* Never cleared.
*/
string error_msg = "";
/**
* Check that a service exists.
* If not, set error_msg.
* @param name service name without a path, eg. nfsserver
* @return Return true if the service exists.
*/
define boolean checkExists (string name) {
if(name == nil || name == "") {
// Error message.
// %1 is a name of an init script in /etc/init.d,
// eg. nfsserver
error_msg = sformat (_("Empty service name: %1."), name);
y2error(1, error_msg);
return false;
}
if(! (boolean) SCR::Read(.init.scripts.exists, name)) {
// Error message.
// %1 is a name of an init script in /etc/init.d,
// eg. nfsserver
error_msg = sformat (_("Service %1 does not exist."), name);
y2error (1, error_msg);
return false;
}
return true;
}
/**
* Get service info without peeking if service runs.
* @param name name of the service
* @return Service information or empty map ($[])
*/
global define map Info (string name) {
if(!checkExists (name)) return $[];
map read = (map) SCR::Read (.init.scripts.runlevel, name);
map detail = read[name]:$[];
read = (map) SCR::Read (.init.scripts.comment, name);
map service = read[name]:$[];
return add (
add (service, "start", detail["start"]:[]),
"stop", detail["stop"]:[]);
}
/**
* Get service status.
*
* The status is the output from "service status".
* It should conform to LSB. 0 means the service is running.
* @param name name of the service
* @return init script exit status or -1 if it does not exist
*/
global define integer Status (string name) {
if(!checkExists (name)) return -1;
return (integer) SCR::Execute (.target.bash, sformat ("%2/%1 status", name, init_d), $["TERM":"raw"]);
}
/**
* Get service info and find out whether service is running.
* @param name name of the service
* @return service map or empty map ($[])
*/
global define map FullInfo (string name) {
if(!checkExists (name)) return $[];
return add (Info (name), "started", Status (name));
}
/**
* Call insserv -r and record errors.
* Does not check if it exists
* @param name service name
* @param force pass "-f" to insserv (workaround for #17608, #27370)
* @return success state
*/
define boolean serviceDisable (string name, boolean force) {
map ret = (map)SCR::Execute (.target.bash_output,
sformat ("/sbin/insserv -r%3 %2/%1",
name, init_d, force? "f": ""));
if (0 != ret["exit"]:-1)
{
// Error message.
// %1 is a name of an init script in /etc/init.d,
// Disabling means that the service should not start
// in appropriate runlevels, eg. at boot time.
// %2 is the stderr output of insserv(8)
error_msg = sformat(_("Unable to disable service %1:\n%2"),
name, ret["stderr"]:"");
// the user is two levels up
y2error (2, error_msg);
return false;
}
return true;
}
/**
* Adjust runlevels in which the service runs.
* @param name service name
* @param action "disable" -- remove links, "enable" -- if there are
* no links, set default, otherwise do nothing, "default" -- set
* defaults.
* @return success state
*/
global define boolean Adjust (string name, string action) {
if (! checkExists (name))
{
return false;
}
map service = Info (name);
if ("disable" == action)
{
if (size (service["start"]:[]) != 0)
{
return serviceDisable (name, false);
}
return true;
}
if (("default" == action) || ("enable" == action))
{
if ("enable" == action && size (service["start"]:[]) != 0)
{
// nothing to do
return true;
}
else
{
map ret = (map)SCR::Execute (.target.bash_output,
sformat ("/sbin/insserv -d %2/%1",
name, init_d));
if (0 != ret["exit"]:-1)
{
// Error message.
// %1 is a name of an init script in /etc/init.d,
// Enabling means that the service should start
// in appropriate runlevels, eg. at boot time.
// %2 is the stderr output of insserv(8)
error_msg = sformat(_("Unable to enable service %1:\n%2"),
name, ret["stderr"]:"");
y2error (1, error_msg);
return false;
}
}
return true;
}
// not translated
error_msg = sformat ("Invalid parameter: %1", action);
y2internal (1, error_msg);
return false;
}
/**
* Set service to run in selected runlevels.
* @param name name of service to adjust
* @param rl list of runlevels in which service should start
* @return success state
*/
global define boolean Finetune (string name, list rl) {
if (! checkExists (name))
{
return false;
}
// Force because of #27370:
// RunlevelEd::Write has already solved the dependencies
// and calls us only once for each modified service.
// In general we cannot do it with dependencies in a single pass.
string rls = mergestring ((list<string>)rl, ",");
// we must remove it first because insserv start=... adds
// runlevels, not replace runlevels!!
if (! serviceDisable (name, true))
{
return false;
}
if (rls != "")
{
map ret = (map)SCR::Execute (.target.bash_output,
sformat ("/sbin/insserv -f %2/%1,start=%3",
name, init_d, rls));
if (0 != ret["exit"]:-1)
{
// Error message.
// %1 is a name of an init script in /etc/init.d,
// Enabling means that the service should start
// in appropriate runlevels, eg. at boot time.
// %2 is the stderr output of insserv(8)
// %3 is a comma separated list of runlevels
error_msg = sformat(_("Unable to enable service %1 in runlevels %2:\n%3"),
name, rls, ret["stderr"]:"");
y2error (1, error_msg);
return false;
}
}
return true;
}
/**
* Check if service is enabled
*
* Returns true if any link in /etc/init.d/rc?.d/ exists for this
* script. If service does not exist, logs an error.
*
* @param name service name
* @return true if service is set to run in any runlevel
*/
global define boolean Enabled (string name) {
if(!checkExists (name)) return false;
map<string, any> details = (map<string, any>) SCR::Read (.init.scripts.runlevel, name);
map<string, any> detail = (map<string, any>) details[name]:$[];
return size(detail["start"]:[]) != 0;
}
/**
* Run init script.
* @param name init service name
* @param param init script argument
* @return integer exit value
*/
global define integer RunInitScript (string name, string param) {
y2milestone("Running service initscript %1 %2", name, param);
return (integer) SCR::Execute (.target.bash,
sformat ("%2/%1 %3", name, init_d, param),
$[ "TERM" : "raw"]);
}
/* Time out for background agent - init script run */
integer script_time_out = 60000;
integer sleep_step = 20;
/**
* Run init script with a time-out.
* @param name init service name
* @param param init script argument
* @return integer exit value
*/
global define integer RunInitScriptWithTimeOut (string name, string param) {
y2milestone("Running service initscript %1 %2", name, param);
string command = sformat ("TERM=dumb %2/%1 %3", name, init_d, param);
// default return code
integer return_code = nil;
// starting the process
boolean started = (boolean)SCR::Execute(.background.run_output_err, command);
if (!started) {
y2error("Cannot run '%1'", command);
return return_code;
}
y2debug("Running: %1", command);
list<string> script_out = [];
integer time_spent = 0;
boolean cont_loop = true;
// while continuing is needed and while it is possible
while (cont_loop && ((boolean) SCR::Read(.background.output_open))) {
if (time_spent >= script_time_out) {
y2error("Command '%1' timed-out after %2 mces", command, time_spent);
cont_loop = false;
}
// sleep a little while
time_spent = time_spent + sleep_step;
sleep(sleep_step);
}
// fetching the return code if not timed-out
if (cont_loop) {
return_code = (integer) SCR::Read(.background.status);
}
y2milestone("Time spent: %1 msecs, retcode: %2", time_spent, return_code);
// killing the process (if it still runs)
SCR::Execute(.background.kill, "");
return return_code;
}
string lang = nil;
/**
* Run init script and return output
*
* Run init script and also return its output (stdout and stderr merged).
* @param name init service name
* @param param init script argument
* @return A map of $[ "stdout" : "...", "stderr" : "...", "exit" : int]
*/
global define map RunInitScriptOutput (string name, string param) {
map env = $["TERM": "raw"];
// encoding problems - append .UTF-8 to LANG
if (lang == nil)
{
map<string, any> ex = (map<string, any>) SCR::Execute (.target.bash_output, "echo -n $LANG");
lang = ex["stdout"]:"";
list ll = splitstring (lang, ".");
lang = ll[0]:"";
if (lang != "")
{
lang = lang + ".UTF-8";
}
y2debug ("LANG: %1", lang);
}
if (lang != "")
{
env = add (env, "LANG", lang);
}
// looks like a bug in bash...
string locale_debug = "";
// locale_debug = "; ls /nono 2>&1; /usr/bin/locale; /usr/bin/env";
return (map)SCR::Execute (.target.bash_output,
sformat ("%2/%1 %3 2>&1", name, init_d, param)
+ locale_debug,
env);
}
/**
* Enable service
* @param service service to be enabled
* @return true if operation is successful
*/
global define boolean Enable(string service) {
if(!checkExists(service)) return false;
y2milestone("Enabling service %1", service);
return Adjust(service, "enable");
}
/**
* Disable service
* @param service service to be disabled
* @return true if operation is successful
*/
global define boolean Disable(string service) {
if(!checkExists(service)) return false;
y2milestone("Disabling service %1", service);
return Adjust(service, "disable");
}
/**
* Start service
* @param service service to be started
* @return true if operation is successful
*/
global define boolean Start(string service) {
if(!checkExists(service)) return false;
integer ret = nil;
y2milestone("Starting service %1", service);
ret = RunInitScript(service, "start");
y2debug("ret=%1", ret);
return ret == 0;
}
/**
* Restart service
* @param service service to be restarted
* @return true if operation is successful
*/
global define boolean Restart(string service) {
if(!checkExists(service)) return false;
integer ret = nil;
y2milestone("Restarting service %1", service);
ret = RunInitScript(service, "restart");
y2debug("ret=%1", ret);
return ret == 0;
}
/**
* Reload service
* @param service service to be reloaded
* @return true if operation is successful
*/
global define boolean Reload(string service) {
if(!checkExists(service)) return false;
integer ret = nil;
y2milestone("Reloading service %1", service);
ret = RunInitScript(service, "reload");
y2debug("ret=%1", ret);
return ret == 0;
}
/**
* Stop service
* @param service service to be stopped
* @return true if operation is successful
*/
global define boolean Stop(string service) {
if(!checkExists(service)) return false;
integer ret = nil;
y2milestone("Stopping service %1", service);
ret = RunInitScript(service, "stop");
y2debug("ret=%1", ret);
return ret == 0;
}
/**
* Error Message
*
* If a Service function returns an error, this function would return
* an error message, including insserv stderr and possibly containing
* newlines.
* @return error message from the last operation
*/
global define string Error() {
return error_msg;
}
/* EOF */
}