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 14ec4561b2e925fc9ca74b758c16ef81b540d445..fa8821afe5a7c94b19578666511841f88dd4ec45 100644 (file)
                                 <term><varname>ConditionPathExists=</varname></term>
                                 <term><varname>ConditionDirectoryNotEmpty=</varname></term>
                                 <term><varname>ConditionKernelCommandLine=</varname></term>
                                 <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
                                 <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
                                 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>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
                                 <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>
                                 applied).</para></listitem>
                         </varlistentry>
                 </variablelist>
index 21da2eb9e94c032778064b3283904ba1532ad5cf..3ab4d4e225e6840af5ddc3fa91b215ec30cfc436 100644 (file)
@@ -64,6 +64,8 @@ static bool test_kernel_command_line(const char *parameter) {
         size_t l, pl;
         bool found = false;
 
         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;
         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;
 }
 
         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);
 
 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_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;
 
         case CONDITION_NULL:
                 return !c->negate;
 
index 2f2689cc6da7b879cc8a500fbab70c6f360b71b0..f4903d76d98ce5a36e37b7114a7b0e89215c748e 100644 (file)
@@ -30,6 +30,7 @@ typedef enum ConditionType {
         CONDITION_PATH_EXISTS,
         CONDITION_DIRECTORY_NOT_EMPTY,
         CONDITION_KERNEL_COMMAND_LINE,
         CONDITION_PATH_EXISTS,
         CONDITION_DIRECTORY_NOT_EMPTY,
         CONDITION_KERNEL_COMMAND_LINE,
+        CONDITION_VIRTUALIZATION,
         CONDITION_NULL,
         _CONDITION_TYPE_MAX,
         _CONDITION_TYPE_INVALID = -1
         CONDITION_NULL,
         _CONDITION_TYPE_MAX,
         _CONDITION_TYPE_INVALID = -1
index eaeaadaea48b3e273c464c0b28912e6b875bbfb0..2e67eccc00bc1fe1e1e01a174cd053ed249ef6c2 100644 (file)
@@ -1503,6 +1503,34 @@ static int config_parse_condition_kernel(
         return 0;
 }
 
         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,
 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_path,   "CONDITION" },
                 { config_parse_condition_kernel, "CONDITION" },
                 { config_parse_condition_null,   "CONDITION" },
+                { config_parse_condition_virt,   "CONDITION" },
         };
 
         assert(f);
         };
 
         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"    },
                 { "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" },
                 { "ConditionNull",          config_parse_condition_null,  u,                                               "Unit"    },
 
                 { "PIDFile",                config_parse_path,            &u->service.pid_file,                            "Service" },