unit: distuingish mandatory from triggering conditions

This commit is contained in:
Lennart Poettering 2011-03-08 03:04:47 +01:00
parent 08672cb507
commit 267632f0ab
6 changed files with 62 additions and 26 deletions

2
TODO
View file

@ -14,8 +14,6 @@ F15:
* hook emergency.target into local-fs.target in some way as OnFailure with isolate * hook emergency.target into local-fs.target in some way as OnFailure with isolate
* introduce simple way to do mandatory conditions (make current conditions mandatory, and introduce =| as non-mandatory conditions)
* mount /dev/.run and /var/run as bind mounts * mount /dev/.run and /var/run as bind mounts
* Make use of UnknownInterface, UnknownObject * Make use of UnknownInterface, UnknownObject

View file

@ -622,8 +622,8 @@
environment and optionally test environment and optionally test
whether it is a specific whether it is a specific
implementation. Takes either boolean implementation. Takes either boolean
value to check if being executed in any value to check if being executed in
virtual environment or one of the any virtual environment or one of the
<varname>qemu</varname>, <varname>qemu</varname>,
<varname>kvm</varname>, <varname>kvm</varname>,
<varname>vmware</varname>, <varname>vmware</varname>,
@ -642,9 +642,20 @@
will always fail, otherwise will always fail, otherwise
succeed. If multiple conditions are succeed. If multiple conditions are
specified the unit will be executed if specified the unit will be executed if
at least one of them applies (i.e. a all of them apply (i.e. a logical AND
logical OR is is applied). Condition checks can be
applied).</para></listitem> prefixed with a pipe symbol (|) in
which case a condition becomes a
triggering condition. If at least one
triggering condition is defined for a
unit then the unit will be executed if
at least one of the triggering
conditions apply and all of the
non-triggering conditions. If you
prefix an argument with the pipe
symbol and an exclamation mark the
pipe symbol must be passed first, the
exclamation second.</para></listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>

View file

@ -27,11 +27,12 @@
#include "util.h" #include "util.h"
#include "condition.h" #include "condition.h"
Condition* condition_new(ConditionType type, const char *parameter, bool negate) { Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
Condition *c; Condition *c;
c = new0(Condition, 1); c = new0(Condition, 1);
c->type = type; c->type = type;
c->trigger = trigger;
c->negate = negate; c->negate = negate;
if (parameter) if (parameter)
@ -153,17 +154,28 @@ bool condition_test(Condition *c) {
bool condition_test_list(Condition *first) { bool condition_test_list(Condition *first) {
Condition *c; Condition *c;
int triggered = -1;
/* If the condition list is empty, then it is true */ /* If the condition list is empty, then it is true */
if (!first) if (!first)
return true; return true;
/* Otherwise, if any of the conditions apply we return true */ /* Otherwise, if all of the non-trigger conditions apply and
LIST_FOREACH(conditions, c, first) * if any of the trigger conditions apply (unless there are
if (condition_test(c)) * none) we return true */
return true; LIST_FOREACH(conditions, c, first) {
bool b;
b = condition_test(c);
if (!c->trigger && !b)
return false; return false;
if (c->trigger && triggered <= 0)
triggered = b;
}
return triggered != 0;
} }
void condition_dump(Condition *c, FILE *f, const char *prefix) { void condition_dump(Condition *c, FILE *f, const char *prefix) {
@ -174,9 +186,10 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
prefix = ""; prefix = "";
fprintf(f, fprintf(f,
"%s%s: %s%s\n", "%s%s: %s%s%s\n",
prefix, prefix,
condition_type_to_string(c->type), condition_type_to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "", c->negate ? "!" : "",
c->parameter); c->parameter);
} }

View file

@ -39,12 +39,14 @@ typedef enum ConditionType {
typedef struct Condition { typedef struct Condition {
ConditionType type; ConditionType type;
char *parameter; char *parameter;
bool negate;
bool trigger:1;
bool negate:1;
LIST_FIELDS(struct Condition, conditions); LIST_FIELDS(struct Condition, conditions);
} Condition; } Condition;
Condition* condition_new(ConditionType type, const char *parameter, bool negate); Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
void condition_free(Condition *c); void condition_free(Condition *c);
void condition_free_list(Condition *c); void condition_free_list(Condition *c);

View file

@ -1397,7 +1397,7 @@ static int config_parse_condition_path(
void *userdata) { void *userdata) {
Unit *u = data; Unit *u = data;
bool negate; bool trigger, negate;
Condition *c; Condition *c;
assert(filename); assert(filename);
@ -1405,6 +1405,9 @@ static int config_parse_condition_path(
assert(rvalue); assert(rvalue);
assert(data); assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!')) if ((negate = rvalue[0] == '!'))
rvalue++; rvalue++;
@ -1414,7 +1417,7 @@ static int config_parse_condition_path(
} }
if (!(c = condition_new(streq(lvalue, "ConditionPathExists") ? CONDITION_PATH_EXISTS : CONDITION_DIRECTORY_NOT_EMPTY, if (!(c = condition_new(streq(lvalue, "ConditionPathExists") ? CONDITION_PATH_EXISTS : CONDITION_DIRECTORY_NOT_EMPTY,
rvalue, negate))) rvalue, trigger, negate)))
return -ENOMEM; return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c); LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@ -1431,7 +1434,7 @@ static int config_parse_condition_kernel(
void *userdata) { void *userdata) {
Unit *u = data; Unit *u = data;
bool negate; bool trigger, negate;
Condition *c; Condition *c;
assert(filename); assert(filename);
@ -1439,10 +1442,13 @@ static int config_parse_condition_kernel(
assert(rvalue); assert(rvalue);
assert(data); assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!')) if ((negate = rvalue[0] == '!'))
rvalue++; rvalue++;
if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, negate))) if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, trigger, negate)))
return -ENOMEM; return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c); LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@ -1459,7 +1465,7 @@ static int config_parse_condition_virt(
void *userdata) { void *userdata) {
Unit *u = data; Unit *u = data;
bool negate; bool trigger, negate;
Condition *c; Condition *c;
assert(filename); assert(filename);
@ -1467,10 +1473,13 @@ static int config_parse_condition_virt(
assert(rvalue); assert(rvalue);
assert(data); assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!')) if ((negate = rvalue[0] == '!'))
rvalue++; rvalue++;
if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, negate))) if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, trigger, negate)))
return -ENOMEM; return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c); LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@ -1488,7 +1497,7 @@ static int config_parse_condition_null(
Unit *u = data; Unit *u = data;
Condition *c; Condition *c;
bool negate; bool trigger, negate;
int b; int b;
assert(filename); assert(filename);
@ -1496,6 +1505,9 @@ static int config_parse_condition_null(
assert(rvalue); assert(rvalue);
assert(data); assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!')) if ((negate = rvalue[0] == '!'))
rvalue++; rvalue++;
@ -1507,7 +1519,7 @@ static int config_parse_condition_null(
if (!b) if (!b)
negate = !negate; negate = !negate;
if (!(c = condition_new(CONDITION_NULL, NULL, negate))) if (!(c = condition_new(CONDITION_NULL, NULL, trigger, negate)))
return -ENOMEM; return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c); LIST_PREPEND(Condition, conditions, u->meta.conditions, c);

View file

@ -11,8 +11,8 @@ DefaultDependencies=no
Conflicts=shutdown.target Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service After=systemd-readahead-collect.service systemd-readahead-replay.service
Before=sysinit.target shutdown.target Before=sysinit.target shutdown.target
ConditionPathExists=/etc/sysctl.conf ConditionPathExists=|/etc/sysctl.conf
ConditionDirectoryNotEmpty=/etc/sysctl.d ConditionDirectoryNotEmpty=|/etc/sysctl.d
[Service] [Service]
Type=oneshot Type=oneshot