]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
Implement generic plugin script support 727/head
authorLudwig Nussel <ludwig.nussel@suse.de>
Wed, 1 Jun 2022 11:14:15 +0000 (13:14 +0200)
committerLudwig Nussel <ludwig.nussel@suse.de>
Wed, 1 Jun 2022 14:20:52 +0000 (16:20 +0200)
Instead of hardcoding calls to specific scripts, just read the
content of /usr/lib/snapper/plugins and execute all scripts that
start with a digit.
Implemented for create_snapshot, modify_snapshot, delete_snapshot,
and set_default_snapshot for a start.

doc/snapper.xml.in
snapper/Btrfs.cc
snapper/Hooks.cc
snapper/Hooks.h
snapper/Snapshot.cc

index d44b3ea11ba69bc9d30675f6cbfaecf39f52dad0..c9d1aa3b5438c30e83017b59ee86ea97a2f4e6c8 100644 (file)
     <citerefentry><refentrytitle>snapper-configs</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
   </refsect1>
 
+  <refsect1 id='plugins'>
+    <title>PLUGINS</title>
+    <para>snapper can execute external scripts after certain actions. Scripts
+    have to be placed in <filename>/usr/lib/snapper/plugins</filename>.
+    The name has to start with a digit, execution order is alphabetical.</para>
+    <para>The first argument of a script is the action snapper executed. The
+      following actions are defined:</para>
+    <variablelist>
+      <varlistentry>
+       <term><option>create-snapshot <replaceable>subvolume</replaceable> <replaceable>snapshot-number</replaceable></option></term>
+       <listitem>
+         <para>Executed when a new snapshot gets created</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><option>delete-snapshot <replaceable>subvolume</replaceable> <replaceable>snapshot-number</replaceable></option></term>
+       <listitem>
+         <para>Executed when a snapshot is removed</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><option>modify-snapshot <replaceable>subvolume</replaceable> <replaceable>snapshot-number</replaceable></option></term>
+       <listitem>
+         <para>Executed when a snapshot gets modified</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><option>set-default-snapshot <replaceable>subvolume</replaceable> <replaceable>snapshot-number</replaceable></option></term>
+       <listitem>
+         <para>Executed when the default snapshot gets changed</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
   <refsect1 id='files'>
     <title>FILES</title>
     <variablelist>
index 02bf167f828d68b1ebad9336e19886c42438c2b8..5dc1e2679574b7a1abd525801c01a1ac38897866 100644 (file)
@@ -51,6 +51,7 @@
 #include "snapper/Btrfs.h"
 #include "snapper/BtrfsUtils.h"
 #include "snapper/File.h"
+#include "snapper/Hooks.h"
 #include "snapper/Snapper.h"
 #include "snapper/SnapperTmpl.h"
 #include "snapper/SnapperDefines.h"
@@ -1530,6 +1531,8 @@ namespace snapper
                SDir snapshot_dir = openSnapshotDir(num);
                subvolid_t id = get_id(snapshot_dir.fd());
                set_default_id(general_dir.fd(), id);
+
+               Hooks::set_default_snapshot(subvolume, this, num);
            }
        }
        catch (const runtime_error& e)
index abd9e30d953fc052efcc719a6c33ac5eff640254..54dec21681468e056b03f00e043e4bbec317e1e6 100644 (file)
 
 #include "config.h"
 
+#include <string.h>
+
+#include <boost/algorithm/string/join.hpp>
+
+#include "snapper/FileUtils.h"
 #include "snapper/Hooks.h"
 #include "snapper/SystemCmd.h"
+#include "snapper/Log.h"
 
 
 namespace snapper
 {
     using namespace std;
 
+    static bool
+    _plugins_filter_entries(unsigned char type, const char* name)
+    {
+       // must start with digit
+       if (*name >= '0' && *name <= '9')
+           return true;
+       return false;
+    }
+
+    void
+    Hooks::run_scripts(const list<string>& args)
+    {
+           SDir dir("/usr/lib/snapper/plugins");
+
+           vector<string> scripts = dir.entries(_plugins_filter_entries);
+           std::sort(scripts.begin(), scripts.end());
+           for (const string& script : scripts)
+           {
+               string cmdln = dir.fullname(script);
+               for (const string& arg : args) {
+                   cmdln += " " + quote(arg);
+               }
+               SystemCmd cmd(cmdln);
+           }
+    }
 
     void
     Hooks::create_config(const string& subvolume, const Filesystem* filesystem)
@@ -46,25 +77,33 @@ namespace snapper
 
 
     void
-    Hooks::create_snapshot(const string& subvolume, const Filesystem* filesystem)
+    Hooks::create_snapshot(const string& subvolume, const Filesystem* filesystem, const Snapshot& snapshot)
     {
        grub(subvolume, filesystem, "--refresh");
+       run_scripts(std::list<string>({"create-snapshot", subvolume, std::to_string(snapshot.getNum())}));
     }
 
 
     void
-    Hooks::modify_snapshot(const string& subvolume, const Filesystem* filesystem)
+    Hooks::modify_snapshot(const string& subvolume, const Filesystem* filesystem, const Snapshot& snapshot)
     {
        grub(subvolume, filesystem, "--refresh");
+       run_scripts(std::list<string>({"modify-snapshot", subvolume, std::to_string(snapshot.getNum())}));
     }
 
 
     void
-    Hooks::delete_snapshot(const string& subvolume, const Filesystem* filesystem)
+    Hooks::delete_snapshot(const string& subvolume, const Filesystem* filesystem, const Snapshot& snapshot)
     {
        grub(subvolume, filesystem, "--refresh");
+       run_scripts(std::list<string>({"delete-snapshot", subvolume, std::to_string(snapshot.getNum())}));
     }
 
+    void
+    Hooks::set_default_snapshot(const string& subvolume, const Filesystem* filesystem, unsigned int num)
+    {
+       run_scripts(std::list<string>({"set-default-snapshot", subvolume, std::to_string(num)}));
+    }
 
     void
     Hooks::grub(const string& subvolume, const Filesystem* filesystem, const char* option)
index befb274a3239863ca9ddd03da487017633194efb..a81fa31ca8b65a682fe2496978cc9094c4faea92 100644 (file)
@@ -37,12 +37,14 @@ namespace snapper
     {
     public:
 
+       static void run_scripts(const list<string>& args);
        static void create_config(const string& subvolume, const Filesystem* filesystem);
        static void delete_config(const string& subvolume, const Filesystem* filesystem);
 
-       static void create_snapshot(const string& subvolume, const Filesystem* filesystem);
-       static void modify_snapshot(const string& subvolume, const Filesystem* filesystem);
-       static void delete_snapshot(const string& subvolume, const Filesystem* filesystem);
+       static void create_snapshot(const string& subvolume, const Filesystem* filesystem, const Snapshot& snapshot);
+       static void modify_snapshot(const string& subvolume, const Filesystem* filesystem, const Snapshot& snapshot);
+       static void delete_snapshot(const string& subvolume, const Filesystem* filesystem, const Snapshot& snapshot);
+       static void set_default_snapshot(const string& subvolume, const Filesystem* filesystem, unsigned int num);
 
        static void rollback(const string& old_root, const string& new_root);
 
index d9c01ac6d9ed01c62521d0245ddd302757731e38..384701a21f96b1b4c70e368d6565bce73836a135 100644 (file)
@@ -733,7 +733,7 @@ namespace snapper
            SN_RETHROW(e);
        }
 
-       Hooks::create_snapshot(snapper->subvolumeDir(), snapper->getFilesystem());
+       Hooks::create_snapshot(snapper->subvolumeDir(), snapper->getFilesystem(), snapshot);
 
        return entries.insert(entries.end(), snapshot);
     }
@@ -753,7 +753,7 @@ namespace snapper
 
        snapshot->writeInfo();
 
-       Hooks::modify_snapshot(snapper->subvolumeDir(), snapper->getFilesystem());
+       Hooks::modify_snapshot(snapper->subvolumeDir(), snapper->getFilesystem(), *snapshot);
     }
 
 
@@ -794,7 +794,7 @@ namespace snapper
 
        entries.erase(snapshot);
 
-       Hooks::delete_snapshot(snapper->subvolumeDir(), snapper->getFilesystem());
+       Hooks::delete_snapshot(snapper->subvolumeDir(), snapper->getFilesystem(), *snapshot);
     }