chiark / gitweb /
unit: introduce ConditionVirtualization=
authorLennart Poettering <lennart@poettering.net>
Mon, 21 Feb 2011 21:07:55 +0000 (22:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 21 Feb 2011 21:07:55 +0000 (22:07 +0100)
man/systemd.unit.xml
src/condition.c
src/condition.h
src/load-fragment.c

index 14ec456..fa8821a 100644 (file)
                                 <term><varname>ConditionPathExists=</varname></term>
                                 <term><varname>ConditionDirectoryNotEmpty=</varname></term>
                                 <term><varname>ConditionKernelCommandLine=</varname></term>
+                                <term><varname>ConditionVirtualization=</varname></term>
                                 <term><varname>ConditionNull=</varname></term>
 
                                 <listitem><para>Before starting a unit
                                 assignment. In the latter case the
                                 exact assignment is looked for with
                                 right and left hand side
-                                matching. Finally,
+                                matching. <varname>ConditionVirtualization=</varname>
+                                may be used to check whether the
+                                system is executed in a virtualized
+                                environment and optionally test
+                                whether it is a specific
+                                implementation. Takes either boolean
+                                value to check if being executed in any
+                                virtual environment or one of the
+                                <varname>qemu</varname>,
+                                <varname>kvm</varname>,
+                                <varname>vmware</varname>,
+                                <varname>microsoft</varname>,
+                                <varname>oracle</varname>,
+                                <varname>xen</varname>,
+                                <varname>openvz</varname> to test
+                                against a specific implementation. The
+                                test may be negated by prepending an
+                                exclamation mark. Finally,
                                 <varname>ConditionNull=</varname> may
                                 be used to add a constant condition
                                 check value to the unit. It takes a
                                 <varname>false</varname> the condition
                                 will always fail, otherwise
                                 succeed. If multiple conditions are
-                                specified the unit will be executed
-                                if at least one of them applies
-                                (i.e. a logical OR is
+                                specified the unit will be executed if
+                                at least one of them applies (i.e. a
+                                logical OR is
                                 applied).</para></listitem>
                         </varlistentry>
                 </variablelist>
index 21da2eb..3ab4d4e 100644 (file)
@@ -64,6 +64,8 @@ static bool test_kernel_command_line(const char *parameter) {
         size_t l, pl;
         bool found = false;
 
+        assert(parameter);
+
         if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
                 return false;
@@ -98,6 +100,28 @@ static bool test_kernel_command_line(const char *parameter) {
         return found;
 }
 
+static bool test_virtualization(const char *parameter) {
+        int r, b;
+        const char *id;
+
+        assert(parameter);
+
+        if ((r = detect_virtualization(&id)) < 0) {
+                log_warning("Failed to detect virtualization, ignoring: %s", strerror(-r));
+                return false;
+        }
+
+        b = parse_boolean(parameter);
+
+        if (r > 0 && b > 0)
+                return true;
+
+        if (r == 0 && b == 0)
+                return true;
+
+        return streq(parameter, id);
+}
+
 bool condition_test(Condition *c) {
         assert(c);
 
@@ -116,6 +140,9 @@ bool condition_test(Condition *c) {
         case CONDITION_KERNEL_COMMAND_LINE:
                 return !!test_kernel_command_line(c->parameter) == !c->negate;
 
+        case CONDITION_VIRTUALIZATION:
+                return !!test_virtualization(c->parameter) == !c->negate;
+
         case CONDITION_NULL:
                 return !c->negate;
 
index 2f2689c..f4903d7 100644 (file)
@@ -30,6 +30,7 @@ typedef enum ConditionType {
         CONDITION_PATH_EXISTS,
         CONDITION_DIRECTORY_NOT_EMPTY,
         CONDITION_KERNEL_COMMAND_LINE,
+        CONDITION_VIRTUALIZATION,
         CONDITION_NULL,
         _CONDITION_TYPE_MAX,
         _CONDITION_TYPE_INVALID = -1
index eaeaada..2e67ecc 100644 (file)
@@ -1503,6 +1503,34 @@ static int config_parse_condition_kernel(
         return 0;
 }
 
+static int config_parse_condition_virt(
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Unit *u = data;
+        bool negate;
+        Condition *c;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if ((negate = rvalue[0] == '!'))
+                rvalue++;
+
+        if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, negate)))
+                return -ENOMEM;
+
+        LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
+        return 0;
+}
+
 static int config_parse_condition_null(
                 const char *filename,
                 unsigned line,
@@ -1714,6 +1742,7 @@ static void dump_items(FILE *f, const ConfigItem *items) {
                 { config_parse_condition_path,   "CONDITION" },
                 { config_parse_condition_kernel, "CONDITION" },
                 { config_parse_condition_null,   "CONDITION" },
+                { config_parse_condition_virt,   "CONDITION" },
         };
 
         assert(f);
@@ -1838,6 +1867,7 @@ static int load_from_path(Unit *u, const char *path) {
                 { "ConditionPathExists",    config_parse_condition_path,  u,                                               "Unit"    },
                 { "ConditionDirectoryNotEmpty", config_parse_condition_path,  u,                                           "Unit"    },
                 { "ConditionKernelCommandLine", config_parse_condition_kernel, u,                                          "Unit"    },
+                { "ConditionVirtualization",config_parse_condition_virt,  u,                                               "Unit"    },
                 { "ConditionNull",          config_parse_condition_null,  u,                                               "Unit"    },
 
                 { "PIDFile",                config_parse_path,            &u->service.pid_file,                            "Service" },