[systemd-devel] [PATCH] systemd: enable/disable instances of template

Michal Sekletar msekleta at redhat.com
Thu Jul 12 07:00:17 PDT 2012


https://bugzilla.redhat.com/show_bug.cgi?id=752774
---
 man/systemctl.xml      |   33 +++++++++--------
 src/shared/install.c   |   93 ++++++++++++++++++++++++++++++++++++++++++------
 src/shared/unit-name.c |   12 +++++++
 src/shared/unit-name.h |    1 +
 4 files changed, 115 insertions(+), 24 deletions(-)

diff --git a/man/systemctl.xml b/man/systemctl.xml
index bf31b61..ba4d972 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -682,24 +682,29 @@
                         <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
-                                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
-                                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
diff --git a/src/shared/install.c b/src/shared/install.c
index a3b7524..a57aca6 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -196,7 +196,8 @@ static int remove_marked_symlinks_fd(
                 const char *config_path,
                 bool *deleted,
                 UnitFileChange **changes,
-                unsigned *n_changes) {
+                unsigned *n_changes,
+                char** files) {
 
         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 */
-                        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)
@@ -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));
 
+                        if (unit_name_is_instance(p))
+                                found = found && strv_contains(files, path_get_file_name(p));
+
                         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,
-                unsigned *n_changes) {
+                unsigned *n_changes,
+                char** files) {
 
         int fd, r = 0;
         bool deleted;
@@ -351,7 +356,7 @@ static int remove_marked_symlinks(
                 }
 
                 /* 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);
@@ -717,7 +722,7 @@ int unit_file_unmask(
 
 
 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;
 
@@ -1094,8 +1099,50 @@ static int unit_file_search(
 
                 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;
+                                }
+
+                                if (isempty(root_dir))
+                                        asprintf(&template_dir, "%s/", *p);
+                                else
+                                        asprintf(&template_dir, "%s/%s/", root_dir, *p);
+
+                                if (!template_dir) {
+                                        free(path);
+                                        free(template);
+                                        return -ENOMEM;
+                                }
+
+                                template_path = join(template_dir, template, NULL);
+                                if (!template_path) {
+                                        free(path);
+                                        free(template);
+                                        free(template_dir);
+                                        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);
+
+                                free(template);
+                                free(template_dir);
+                                free(template_path);
+                        }
                         free(path);
+                }
 
                 if (r != -ENOENT && r != -ELOOP)
                         return r;
@@ -1419,7 +1466,33 @@ static int install_context_mark_for_removal(
                 } else if (r >= 0)
                         r += q;
 
-                q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+                if (unit_name_is_instance(i->name)) {
+                        char *template = NULL,
+                             *instance_path = NULL;
+
+                        /* create path to instance */
+                        instance_path = new0(char, strrchr(i->path, '/') - i->path + strlen(i->name) + 2);
+                        memcpy(instance_path, i->path, strrchr(i->path, '/') - i->path + 1);
+                        memcpy(instance_path + strlen(instance_path), i->name, strlen(i->name));
+
+                        /* check if unit file named same as an instance exits*/
+                        if (access(instance_path, R_OK) && errno == ENOENT) {
+                                /* does not exist, thus we will mark for removal symlinks to template unit file */
+                                template = unit_name_template(i->name);
+                                if (!template) {
+                                        free(instance_path);
+                                        return -ENOMEM;
+                                }
+                                q = mark_symlink_for_removal(remove_symlinks_to, template);
+                        } else
+                                /* unit file with named as instance exists, thus all symlinks pointing to it, will be removed */
+                                q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+
+                        free(template);
+                        free(instance_path);
+                } else
+                        q = mark_symlink_for_removal(remove_symlinks_to, i->name);
+
                 if (r >= 0 && q < 0)
                         r = q;
         }
@@ -1511,7 +1584,7 @@ int unit_file_disable(
 
         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;
 
@@ -1563,7 +1636,7 @@ int unit_file_reenable(
                         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);
@@ -1813,7 +1886,7 @@ int unit_file_preset(
 
         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;
 
diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c
index 3e437b7..ba88061 100644
--- a/src/shared/unit-name.c
+++ b/src/shared/unit-name.c
@@ -341,6 +341,18 @@ bool unit_name_is_template(const char *n) {
         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;
diff --git a/src/shared/unit-name.h b/src/shared/unit-name.h
index c6c09dd..b398258 100644
--- a/src/shared/unit-name.h
+++ b/src/shared/unit-name.h
@@ -80,6 +80,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);
+bool unit_name_is_instance(const char *n);
 
 char *unit_name_replace_instance(const char *f, const char *i);
 
-- 
1.7.10.4



More information about the systemd-devel mailing list