Skip to content

Commit

Permalink
Unified starting services using EnableAndStartServices
Browse files Browse the repository at this point in the history
  • Loading branch information
kobliha committed Nov 19, 2012
1 parent fd11fd1 commit 693a739
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 106 deletions.
209 changes: 160 additions & 49 deletions src/RunlevelEd.ycp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
* Martin Vidner <mvidner@suse.cz>
* Petr Blahos <pblahos@suse.cz>
* Martin Lazar <mlazar@suse.cz>
* Lukas Ocilka <locilka@suse.com>
* Ladislav Slezak <lslezak@suse.com>
*
* $Id$
*/
Expand All @@ -27,6 +29,7 @@
import "ProductFeatures";
import "Systemd";
import "Message";
import "Mode";

include "runlevel/toposort.ycp";

Expand Down Expand Up @@ -90,40 +93,37 @@
/**
* @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

// "should" dependencies (+) are filtered by addRequires
"reqstart" : [ "$network", "portmap" ], // Required-Start comment
"reqstop" : [ "$network", "portmap" ], // Required-Stop comment

"shortdescription" : "text...", // Description comment
"description" : "text...", // Description comment

// which runlevels service is really started/stopped in
// read from /etc/init.d/{rc?,boot}.d/* links
//
// Note that the boot process (init.d/boot.d) is considered
// a "B" runlevel that is implicitly contained in the other runlevels.
// Using
// list st = services ["boot.local", "start"]:[]
// contains (st, "3") // DON'T
// results in false but that's probably not what you want.
// Use
// StartContainsImplicitly (st, "3")
// which tests for "3" and "B".
"start" : [ "3", "5", ],
"stop" : [ "3", "5", ],

"started" : 0, // return from rcservice status (integer)

"dirty" : false, // was the entry changed?
]</pre>
"servicename" : $[
"defstart" : [ "2", "3", "5", ], // Default-Start comment
"defstop" : [ "0", "1", "6", ], // Default-Stop comment
// "should" dependencies (+) are filtered by addRequires
"reqstart" : [ "$network", "portmap" ], // Required-Start comment
"reqstop" : [ "$network", "portmap" ], // Required-Stop comment
"shortdescription" : "text...", // Description comment
"description" : "text...", // Description comment
// which runlevels service is really started/stopped in
// read from /etc/init.d/{rc?,boot}.d/* links
//
// Note that the boot process (init.d/boot.d) is considered
// a "B" runlevel that is implicitly contained in the other runlevels.
// Using
// list st = services ["boot.local", "start"]:[]
// contains (st, "3") // DON'T
// results in false but that's probably not what you want.
// Use
// StartContainsImplicitly (st, "3")
// which tests for "3" and "B".
"start" : [ "3", "5", ],
"stop" : [ "3", "5", ],
"started" : 0, // return from rcservice status (integer)
"dirty" : false, // was the entry changed?
]</pre>
*/
//
//


/**
* List of all services. Each item is a map described above.
Expand Down Expand Up @@ -505,26 +505,135 @@ Further dependency checking will be disabled."));

global string GetCurrentRunlevel();

global string GetDefaultRunlevel();

/**
* Returns list of services that should be running now().
* On running system it's only those services that were changed during
* configuration (so-called 'dirty'). In AutoYast it's all services.
* In all cases boot.* services are excluded.
*/
global list <string> ListOfServicesToStart () {
boolean in_autoyast = Mode::autoinst() || Mode::config();
list <string> services_to_start = [];
string current_runlevel = GetCurrentRunlevel();

// In AutoYast the current runlevel doesn't matter
// the imported one (default_runlevel) does.
if (in_autoyast) {
current_runlevel = GetDefaultRunlevel();
}

y2milestone("Current runlevel: %1", current_runlevel);

foreach (string service, map details, services, {
// boot.* services are ignored
if (regexpmatch (service, "^boot\..*"))
return;

// these services should not be running now
if (!contains(details["start"]:[], current_runlevel))
return;

// in_autoyast? -> all services
// otherwise only the 'dirty' ones
if (!in_autoyast && !details["dirty"]:false)
return;

services_to_start = add(services_to_start, service);
});

y2milestone("Services to start: %1", services_to_start);

return services_to_start;
}

/**
* Starts service given as parameter if the current runlevel
* is listed within runlevels given as the second parameter.
* Returns list of runlevels in which the service given as argument
* should start
*
* @param string service
* @param list service runlevels
* @param string service name
* @param list <string> list of runlevels
*/
define boolean StartIfNeeded(string service, list <string> service_runlevels) {
if (contains(service_runlevels, GetCurrentRunlevel())) {
if (Service::Start(service)) {
y2milestone ("Service %1 has been started", service);
return true;
list <string> StartServiceInRunlevels(string service) {
if (!haskey(services, service)) {
y2error("Unknown service %1", service);
return [];
}

map start_service = services["service"]:$[];

// user-defined values
if (haskey(start_service, "start")) {
return (list <string>) start_service["start"]:[];
// default values
} else if (haskey(start_service, "defstart")) {
return (list <string>) start_service["defstart"]:[];
} else {
y2error ("No 'start' or 'defstart' key in %1", start_service);
return [];
}
}

/**
* Enables and starts services with their dependencies.
* Already running services are kept untouched.
*
* @param list <string> services to start
*/
global boolean EnableAndStartServices (list <string> services) {
boolean ret = true;

list <string> all_needed_services = [];

// Find all the services dependencies first
foreach (string service, services, {
list <string> needed_services = RunlevelEd::ServiceDependencies (service, true);

if (needed_services != nil && needed_services != []) {
y2milestone("Service dependencies for %1 are: %2", service, needed_services);
all_needed_services = (list <string>) union (all_needed_services, needed_services);
}
});

// Prepend services dependencies ...
all_needed_services = toset (all_needed_services);
// ... to list of services to enable
services = (list <string>) union (all_needed_services, services);

foreach (string service, services, {
list <string> runlevels_start = StartServiceInRunlevels(service);

// Check and enable service
if (Service::Enabled (service) != true && Service::Finetune (service, runlevels_start) != true) {
y2error ("Unable to enable service %1", service);
Report::Error (sformat(_("Cannot enable service %1"), service));
ret = false;
}

// All boot.* scripts are skipped
// See BNC #583773
if (regexpmatch (service, "^boot\..*")) {
y2warning ("Skipping service %1", service);
return;
}

// Check and start service
if (Service::Status (service) == -1) {
y2error ("Service name %1 is unknown", service);
Report::Error (sformat (_("Unable to start and enable service %1.
Service is not installed."), service));
ret = false;
} else {
y2error("Cannot start service %1", service);
Report::Error(Message::CannotStartService(service));
return false;
if (Service::RunInitScriptWithTimeOut (service, "status") != 0 && Service::RunInitScriptWithTimeOut (service, "start") != 0) {
y2error ("Unable to start service %1", service);
Report::Error(Message::CannotStartService(service));
ret = false;
}
}
}
});

return true;
return ret;
}

/**
Expand Down Expand Up @@ -569,9 +678,9 @@ Further dependency checking will be disabled."));
list <string> start = v["start"]:[];
y2milestone ("Setting %1: %2", k, start);
string verbose = sformat(_("Setting %1: %2"), k, start);
// this can also disable some services
CommandLine::PrintVerbose(verbose);
fail = ! Service::Finetune (k, start);
StartIfNeeded(k, start);
}
else
// progress item, %1 is a service (init script) name
Expand All @@ -586,7 +695,9 @@ Further dependency checking will be disabled."));
Report::Error (sformat (_("Failed services: %1."), failed_s));
return false;
}
return true;

// Enable and start all services that should be started
return EnableAndStartServices(ListOfServicesToStart());
}

/**
Expand Down
58 changes: 1 addition & 57 deletions src/services_proposal.ycp
Original file line number Diff line number Diff line change
Expand Up @@ -272,62 +272,6 @@ void DisableAndStopServices (list <string> services) {
});
}

/**
* Enables and starts services with their dependencies.
*/
boolean EnableAndStartServices (list <string> services) {
boolean ret = true;

list <string> all_needed_services = [];

// Find all the services dependencies first
foreach (string service, services, {
list <string> needed_services = RunlevelEd::ServiceDependencies (service, true);

if (needed_services != nil && needed_services != []) {
y2milestone("Service dependencies for %1 are: %2", service, needed_services);
all_needed_services = (list <string>) union (all_needed_services, needed_services);
}
});

// Prepend services dependencies ...
all_needed_services = toset (all_needed_services);
// ... to list of services to enable
services = (list <string>) union (all_needed_services, services);

foreach (string service, services, {
// Check and enable service
if (Service::Enabled (service) != true && Service::Enable (service) != true) {
y2error ("Unable to enable service %1", service);
Report::Error (sformat(_("Cannot enable service %1"), service));
ret = false;
}

// All boot.* scripts are skipped
// See BNC #583773
if (regexpmatch (service, "^boot\..*")) {
y2warning ("Skipping service %1", service);
return;
}

// Check and start service
if (Service::Status (service) == -1) {
y2error ("Service name %1 is unknown", service);
Report::Error (sformat (_("Unable to start and enable service %1.
Service is not installed."), service));
ret = false;
} else {
if (Service::RunInitScriptWithTimeOut (service, "status") != 0 && Service::RunInitScriptWithTimeOut (service, "start") != 0) {
y2error ("Unable to start service %1", service);
Report::Error (sformat(_("Cannot start service %1"), service));
ret = false;
}
}
});

return ret;
}

/**
* Opens ports using firewall services got as parameter.
* Services are actually in format "service_name", not
Expand Down Expand Up @@ -431,7 +375,7 @@ enabling and starting the services may also fail."));
}

// Enabling services
if (EnableAndStartServices (services) != true) {
if (RunlevelEd::EnableAndStartServices (services) != true) {
ret = false;
// next service
return;
Expand Down

0 comments on commit 693a739

Please sign in to comment.