chiark / gitweb /
systemd: enable/disable instances of template
authorMichal Sekletar <msekleta@redhat.com>
Fri, 13 Jul 2012 13:59:26 +0000 (15:59 +0200)
committerMichal Schmidt <mschmidt@redhat.com>
Thu, 26 Jul 2012 08:02:10 +0000 (10:02 +0200)
https://bugzilla.redhat.com/show_bug.cgi?id=752774

man/systemctl.xml
src/shared/install.c
src/shared/unit-name.c
src/shared/unit-name.h

index 3c0a7950a0ab367f20961f8ca543ed311d668f1e..c5fae825aa1e80ce3a918bab70e7b6a14a8b8692 100644 (file)
                         <varlistentry>
                                 <term><command>enable [NAME...]</command></term>
 
                         <varlistentry>
                                 <term><command>enable [NAME...]</command></term>
 
-                                <listitem><para>Enable one or more
-                                unit files, as specified on the
+                                <listitem><para>Enable one or
+                                more unit files or unit file
+                                instances, as specified on the
                                 command line. This will create a
                                 command line. This will create a
-                                number of symlinks as encoded in the
-                                <literal>[Install]</literal> sections
-                                of the unit files. After the symlinks
-                                have been created the systemd
-                                configuration is reloaded (in a way
-                                that is equivalent to
-                                <command>daemon-reload</command>) to
-                                ensure the changes are taken into
+                                number of symlinks as encoded in
+                                the <literal>[Install]</literal>
+                                sections of the unit files. After
+                                the symlinks have been created the
+                                systemd configuration is reloaded
+                                (in a way that is equivalent to
+                                <command>daemon-reload</command>)
+                                to ensure the changes are taken into
                                 account immediately. Note that this
                                 does not have the effect that any of
                                 the units enabled are also started at
                                 account immediately. Note that this
                                 does not have the effect that any of
                                 the units enabled are also started at
-                                the same time. If this is desired a
-                                separate <command>start</command>
-                                command must be invoked for the
-                                unit.</para>
+                                the same time.  If this is desired
+                                a separate <command>start</command>
+                                command must be invoked for the unit.
+                                Also note that in case of instance
+                                enablement, symlinks named same as
+                                instances are created in install
+                                location, however they all point to
+                                the same template unit file.</para>
 
                                 <para>This command will
                                 print the actions executed. This
 
                                 <para>This command will
                                 print the actions executed. This
index a3b75243d5dce6e382b4f4edc196b64f42a80e29..ef1c3f584d3a4d28c9c76eb4326d37070a31cdc8 100644 (file)
@@ -196,7 +196,8 @@ static int remove_marked_symlinks_fd(
                 const char *config_path,
                 bool *deleted,
                 UnitFileChange **changes,
                 const char *config_path,
                 bool *deleted,
                 UnitFileChange **changes,
-                unsigned *n_changes) {
+                unsigned *n_changes,
+                char** files) {
 
         int r = 0;
         DIR *d;
 
         int r = 0;
         DIR *d;
@@ -255,7 +256,7 @@ static int remove_marked_symlinks_fd(
                         }
 
                         /* This will close nfd, regardless whether it succeeds or not */
                         }
 
                         /* This will close nfd, regardless whether it succeeds or not */
-                        q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes);
+                        q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, deleted, changes, n_changes, files);
                         free(p);
 
                         if (r == 0)
                         free(p);
 
                         if (r == 0)
@@ -288,6 +289,9 @@ static int remove_marked_symlinks_fd(
                                 set_get(remove_symlinks_to, dest) ||
                                 set_get(remove_symlinks_to, path_get_file_name(dest));
 
                                 set_get(remove_symlinks_to, dest) ||
                                 set_get(remove_symlinks_to, path_get_file_name(dest));
 
+                        if (unit_name_is_instance(p))
+                                found = found && strv_contains(files, path_get_file_name(p));
+
                         if (found) {
 
                                 if (unlink(p) < 0 && errno != ENOENT) {
                         if (found) {
 
                                 if (unlink(p) < 0 && errno != ENOENT) {
@@ -326,7 +330,8 @@ static int remove_marked_symlinks(
                 Set *remove_symlinks_to,
                 const char *config_path,
                 UnitFileChange **changes,
                 Set *remove_symlinks_to,
                 const char *config_path,
                 UnitFileChange **changes,
-                unsigned *n_changes) {
+                unsigned *n_changes,
+                char** files) {
 
         int fd, r = 0;
         bool deleted;
 
         int fd, r = 0;
         bool deleted;
@@ -351,7 +356,7 @@ static int remove_marked_symlinks(
                 }
 
                 /* This takes possession of cfd and closes it */
                 }
 
                 /* This takes possession of cfd and closes it */
-                q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes);
+                q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, &deleted, changes, n_changes, files);
                 if (r == 0)
                         r = q;
         } while (deleted);
                 if (r == 0)
                         r = q;
         } while (deleted);
@@ -717,7 +722,7 @@ int unit_file_unmask(
 
 
 finish:
 
 
 finish:
-        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
+        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
         if (r == 0)
                 r = q;
 
         if (r == 0)
                 r = q;
 
@@ -1094,8 +1099,48 @@ static int unit_file_search(
 
                 if (r >= 0)
                         info->path = path;
 
                 if (r >= 0)
                         info->path = path;
-                else
+                else {
+                        if (r == -ENOENT && unit_name_is_instance(info->name)) {
+                                /* unit file doesn't exist, however instance enablement was request */
+                                /* we will check if it is possible to load template unit file */
+                                char *template = NULL,
+                                     *template_path = NULL,
+                                     *template_dir = NULL;
+
+                                template = unit_name_template(info->name);
+                                if (!template) {
+                                        free(path);
+                                        return -ENOMEM;
+                                }
+
+                                /* we will reuse path variable since we don't need it anymore */
+                                template_dir = path;
+                                *(strrchr(path, '/') + 1) = '\0';
+
+                                template_path = strjoin(template_dir, template, NULL);
+                                if (!template_path) {
+                                        free(path);
+                                        free(template);
+                                        return -ENOMEM;
+                                }
+
+                                /* let's try to load template unit */
+                                r = unit_file_load(c, info, template_path, allow_symlink);
+                                if (r >= 0) {
+                                        info->path = strdup(template_path);
+                                        if (!info->path) {
+                                                free(path);
+                                                free(template);
+                                                free(template_path);
+                                                return -ENOMEM;
+                                        }
+                                }
+
+                                free(template);
+                                free(template_path);
+                        }
                         free(path);
                         free(path);
+                }
 
                 if (r != -ENOENT && r != -ELOOP)
                         return r;
 
                 if (r != -ENOENT && r != -ELOOP)
                         return r;
@@ -1419,7 +1464,20 @@ static int install_context_mark_for_removal(
                 } else if (r >= 0)
                         r += q;
 
                 } else if (r >= 0)
                         r += q;
 
-                q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+                if (unit_name_is_instance(i->name)) {
+                        char *unit_file = NULL;
+
+                        unit_file = path_get_file_name(i->path);
+
+                        if (unit_name_is_instance(unit_file))
+                                /* unit file named as instance exists, thus all symlinks pointing to it, will be removed */
+                                q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+                        else
+                                /* does not exist, thus we will mark for removal symlinks to template unit file */
+                                q = mark_symlink_for_removal(remove_symlinks_to, unit_file);
+                } else
+                        q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+
                 if (r >= 0 && q < 0)
                         r = q;
         }
                 if (r >= 0 && q < 0)
                         r = q;
         }
@@ -1511,7 +1569,7 @@ int unit_file_disable(
 
         r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
 
 
         r = install_context_mark_for_removal(&c, &paths, &remove_symlinks_to, config_path, root_dir);
 
-        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
+        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
         if (r == 0)
                 r = q;
 
         if (r == 0)
                 r = q;
 
@@ -1563,7 +1621,7 @@ int unit_file_reenable(
                         goto finish;
         }
 
                         goto finish;
         }
 
-        r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
+        r = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
 
         /* Returns number of symlinks that where supposed to be installed. */
         q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
 
         /* Returns number of symlinks that where supposed to be installed. */
         q = install_context_apply(&c, &paths, config_path, root_dir, force, changes, n_changes);
@@ -1813,7 +1871,7 @@ int unit_file_preset(
 
         r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
 
 
         r = install_context_mark_for_removal(&minus, &paths, &remove_symlinks_to, config_path, root_dir);
 
-        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes);
+        q = remove_marked_symlinks(remove_symlinks_to, config_path, changes, n_changes, files);
         if (r == 0)
                 r = q;
 
         if (r == 0)
                 r = q;
 
index fcf5902c78409041695b823acd95c04294f23b7f..e8328c321a05363c5ef4fe3f901e126731944618 100644 (file)
@@ -341,6 +341,18 @@ bool unit_name_is_template(const char *n) {
         return p[1] == '.';
 }
 
         return p[1] == '.';
 }
 
+bool unit_name_is_instance(const char *n) {
+        const char *p;
+
+        assert(n);
+
+        p = strchr(n, '@');
+        if (!p)
+                return false;
+
+        return p[1] != '.';
+}
+
 char *unit_name_replace_instance(const char *f, const char *i) {
         const char *p, *e;
         char *r, *k;
 char *unit_name_replace_instance(const char *f, const char *i) {
         const char *p, *e;
         char *r, *k;
index f899f865285c3fea38119fd35baafd05287b2a33..7be346590e645546d2ec5a3f827460e2126f3097 100644 (file)
@@ -79,6 +79,7 @@ char *unit_name_path_escape(const char *f);
 char *unit_name_path_unescape(const char *f);
 
 bool unit_name_is_template(const char *n);
 char *unit_name_path_unescape(const char *f);
 
 bool unit_name_is_template(const char *n);
+bool unit_name_is_instance(const char *n);
 
 char *unit_name_replace_instance(const char *f, const char *i);
 
 
 char *unit_name_replace_instance(const char *f, const char *i);