]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- allow to delete a configuration
authorArvin Schnell <aschnell@suse.de>
Fri, 23 Dec 2011 14:33:35 +0000 (15:33 +0100)
committerArvin Schnell <aschnell@suse.de>
Fri, 23 Dec 2011 14:33:35 +0000 (15:33 +0100)
doc/snapper.8.in
package/snapper.changes
snapper/Filesystem.cc
snapper/Filesystem.h
snapper/Snapper.cc
snapper/Snapper.h
snapper/SnapperDefines.h
tools/snapper.cc

index 499fccccc27ac72fe443220299eae66b524e59d7..5ecee0b151a2ead1914816ab69c11249947c5552 100644 (file)
@@ -121,6 +121,12 @@ this option snapper detect the filesystem.
 \fI\-t, \-\-template\fR <name>
 Name of template for the new configuration file.
 
+.TP
+.B delete-config
+Delete a configuration for a filesystem or subvolume. For this command you
+will likely need to global option \fI--config\fR, see \fBGLOBAL OPTIONS\fR and
+\fBCONCEPTS\fR.
+
 .TP
 .B list [options]
 List snapshots.
index 0f88d5b7cb83446c64c71f669bc28c0a7e48f40e..96460b740ed46f581f81f5305a8e92cc38e3ea0a 100644 (file)
@@ -1,3 +1,8 @@
+-------------------------------------------------------------------
+Fri Dec 23 15:33:12 CET 2011 - aschnell@suse.de
+
+- allow to delete a configuration
+
 -------------------------------------------------------------------
 Thu Nov 24 14:09:15 CET 2011 - aschnell@suse.de
 
index b5b09cbedf08520c8036074c79b11cf324c58e88..3839608df04bbfed7a5b22f6af171e42135766ca 100644 (file)
@@ -61,11 +61,20 @@ namespace snapper
 
 
     void
-    Btrfs::addConfig() const
+    Btrfs::createConfig() const
     {
        SystemCmd cmd2(BTRFSBIN " subvolume create " + quote(subvolume + "/.snapshots"));
        if (cmd2.retcode() != 0)
-           throw AddConfigFailedException("creating btrfs snapshot failed");
+           throw CreateConfigFailedException("creating btrfs snapshot failed");
+    }
+
+
+    void
+    Btrfs::deleteConfig() const
+    {
+       SystemCmd cmd2(BTRFSBIN " subvolume delete " + quote(subvolume + "/.snapshots"));
+       if (cmd2.retcode() != 0)
+           throw DeleteConfigFailedException("deleting btrfs snapshot failed");
     }
 
 
@@ -145,19 +154,19 @@ namespace snapper
 
 
     void
-    Ext4::addConfig() const
+    Ext4::createConfig() const
     {
        int r1 = mkdir((subvolume + "/.snapshots").c_str(), 700);
        if (r1 == 0)
        {
            SystemCmd cmd1(CHATTRBIN " +x " + quote(subvolume + "/.snapshots"));
            if (cmd1.retcode() != 0)
-               throw AddConfigFailedException("chattr failed");
+               throw CreateConfigFailedException("chattr failed");
        }
        else if (errno != EEXIST)
        {
            y2err("mkdir failed errno:" << errno << " (" << strerror(errno) << ")");
-           throw AddConfigFailedException("mkdir failed");
+           throw CreateConfigFailedException("mkdir failed");
        }
 
        int r2 = mkdir((subvolume + "/.snapshots/.info").c_str(), 700);
@@ -165,12 +174,31 @@ namespace snapper
        {
            SystemCmd cmd2(CHATTRBIN " -x " + quote(subvolume + "/.snapshots/.info"));
            if (cmd2.retcode() != 0)
-               throw AddConfigFailedException("chattr failed");
+               throw CreateConfigFailedException("chattr failed");
        }
        else if (errno != EEXIST)
        {
            y2err("mkdir failed errno:" << errno << " (" << strerror(errno) << ")");
-           throw AddConfigFailedException("mkdir failed");
+           throw CreateConfigFailedException("mkdir failed");
+       }
+    }
+
+
+    void
+    Ext4::deleteConfig() const
+    {
+       int r1 = rmdir((subvolume + "/.snapshots/.info").c_str());
+       if (r1 != 0)
+       {
+           y2err("rmdir failed errno:" << errno << " (" << strerror(errno) << ")");
+           throw DeleteConfigFailedException("rmdir failed");
+       }
+
+       int r2 = rmdir((subvolume + "/.snapshots").c_str());
+       if (r2 != 0)
+       {
+           y2err("rmdir failed errno:" << errno << " (" << strerror(errno) << ")");
+           throw DeleteConfigFailedException("rmdir failed");
        }
     }
 
index c5ff827f81026e7e8bb26cfb5599565640d2e468..0c44d66a9b984a02e8906e063254618d78151508 100644 (file)
@@ -46,7 +46,8 @@ namespace snapper
 
        virtual string name() const = 0;
 
-       virtual void addConfig() const = 0;
+       virtual void createConfig() const = 0;
+       virtual void deleteConfig() const = 0;
 
        virtual string infosDir() const = 0;
        virtual string snapshotDir(unsigned int num) const = 0;
@@ -75,7 +76,8 @@ namespace snapper
 
        virtual string name() const { return "btrfs"; }
 
-       virtual void addConfig() const;
+       virtual void createConfig() const;
+       virtual void deleteConfig() const;
 
        virtual string infosDir() const;
        virtual string snapshotDir(unsigned int num) const;
@@ -100,7 +102,8 @@ namespace snapper
 
        virtual string name() const { return "ext4"; }
 
-       virtual void addConfig() const;
+       virtual void createConfig() const;
+       virtual void deleteConfig() const;
 
        virtual string infosDir() const;
        virtual string snapshotDir(unsigned int num) const;
index 0425f2a3e1b631a5c9aa8e996e875e00c9191930..a009324e43b13cdcbe7f5ce6c11f39010bbd81a8 100644 (file)
@@ -539,7 +539,7 @@ namespace snapper
        }
        catch (const FileNotFoundException& e)
        {
-           throw ListConfigsFailedException("sysconfig file not found");
+           throw ListConfigsFailedException("sysconfig-file not found");
        }
 
        return config_infos;
@@ -547,22 +547,22 @@ namespace snapper
 
 
     void
-    Snapper::addConfig(const string& config_name, const string& subvolume,
-                      const string& fstype, const string& template_name)
+    Snapper::createConfig(const string& config_name, const string& subvolume,
+                         const string& fstype, const string& template_name)
     {
-       y2mil("Snapper add-config");
+       y2mil("Snapper create-config");
        y2mil("libsnapper version " VERSION);
        y2mil("config_name:" << config_name << " subvolume:" << subvolume <<
              " fstype:" << fstype << " template_name:" << template_name);
 
        if (config_name.empty() || config_name.find_first_of(", \t") != string::npos)
        {
-           throw AddConfigFailedException("illegal config name");
+           throw CreateConfigFailedException("illegal config name");
        }
 
        if (!boost::starts_with(subvolume, "/") || !checkDir(subvolume))
        {
-           throw AddConfigFailedException("illegal subvolume");
+           throw CreateConfigFailedException("illegal subvolume");
        }
 
        list<ConfigInfo> configs = getConfigs();
@@ -570,13 +570,13 @@ namespace snapper
        {
            if (it->subvolume == subvolume)
            {
-               throw AddConfigFailedException("subvolume already covered");
+               throw CreateConfigFailedException("subvolume already covered");
            }
        }
 
        if (access(string(CONFIGTEMPLATEDIR "/" + template_name).c_str(), R_OK) != 0)
        {
-           throw AddConfigFailedException("cannot access template config");
+           throw CreateConfigFailedException("cannot access template config");
        }
 
        auto_ptr<Filesystem> filesystem;
@@ -586,11 +586,11 @@ namespace snapper
        }
        catch (const InvalidConfigException& e)
        {
-           throw AddConfigFailedException("invalid filesystem type");
+           throw CreateConfigFailedException("invalid filesystem type");
        }
        catch (const ProgramNotInstalledException& e)
        {
-           throw AddConfigFailedException(e.what());
+           throw CreateConfigFailedException(e.what());
        }
 
        try
@@ -600,7 +600,7 @@ namespace snapper
            sysconfig.getValue("SNAPPER_CONFIGS", config_names);
            if (find(config_names.begin(), config_names.end(), config_name) != config_names.end())
            {
-               throw AddConfigFailedException("config already exists");
+               throw CreateConfigFailedException("config already exists");
            }
 
            config_names.push_back(config_name);
@@ -608,14 +608,14 @@ namespace snapper
        }
        catch (const FileNotFoundException& e)
        {
-           throw AddConfigFailedException("sysconfig file not found");
+           throw CreateConfigFailedException("sysconfig-file not found");
        }
 
        SystemCmd cmd1(CPBIN " " + quote(CONFIGTEMPLATEDIR "/" + template_name) + " " +
                       quote(CONFIGSDIR "/" + config_name));
        if (cmd1.retcode() != 0)
        {
-           throw AddConfigFailedException("copying config template failed");
+           throw CreateConfigFailedException("copying config-file template failed");
        }
 
        try
@@ -626,10 +626,67 @@ namespace snapper
        }
        catch (const FileNotFoundException& e)
        {
-           throw AddConfigFailedException("modifying config failed");
+           throw CreateConfigFailedException("modifying config failed");
        }
 
-       filesystem->addConfig();
+       filesystem->createConfig();
+    }
+
+
+    void
+    Snapper::deleteConfig(const string& config_name)
+    {
+       y2mil("Snapper delete-config");
+       y2mil("libsnapper version " VERSION);
+
+       auto_ptr<Snapper> snapper(new Snapper(config_name));
+
+       Snapshots& snapshots = snapper->getSnapshots();
+       for (Snapshots::iterator it = snapshots.begin(); it != snapshots.end(); )
+       {
+           Snapshots::iterator tmp = it++;
+
+           if (tmp->isCurrent())
+               continue;
+
+           try
+           {
+               snapper->deleteSnapshot(tmp);
+           }
+           catch (const DeleteSnapshotFailedException& e)
+           {
+               // ignore, Filesystem->deleteConfig will fail anyway
+           }
+       }
+
+       try
+       {
+           snapper->getFilesystem()->deleteConfig();
+       }
+       catch (const DeleteConfigFailedException& e)
+       {
+           throw DeleteConfigFailedException("deleting snapshot failed");
+       }
+
+       SystemCmd cmd1(RMBIN " " + quote(CONFIGSDIR "/" + config_name));
+       if (cmd1.retcode() != 0)
+       {
+           throw DeleteConfigFailedException("deleting config-file failed");
+       }
+
+       try
+       {
+           SysconfigFile sysconfig(SYSCONFIGFILE);
+           vector<string> config_names;
+           sysconfig.getValue("SNAPPER_CONFIGS", config_names);
+           config_names.erase(remove(config_names.begin(), config_names.end(), config_name),
+                              config_names.end());
+           sysconfig.setValue("SNAPPER_CONFIGS", config_names);
+       }
+       catch (const FileNotFoundException& e)
+       {
+           throw DeleteConfigFailedException("sysconfig-file not found");
+       }
     }
 
 
index 6b234904f330ffb42c2c98f827cb8d94644123a9..f640f679ccd6192b1b70ec541d0c0a171bd49590 100644 (file)
@@ -100,9 +100,16 @@ namespace snapper
        const char* msg;
     };
 
-    struct AddConfigFailedException : public SnapperException
+    struct CreateConfigFailedException : public SnapperException
     {
-       explicit AddConfigFailedException(const char* msg) throw() : msg(msg) {}
+       explicit CreateConfigFailedException(const char* msg) throw() : msg(msg) {}
+       virtual const char* what() const throw() { return msg; }
+       const char* msg;
+    };
+
+    struct DeleteConfigFailedException : public SnapperException
+    {
+       explicit DeleteConfigFailedException(const char* msg) throw() : msg(msg) {}
        virtual const char* what() const throw() { return msg; }
        const char* msg;
     };
@@ -147,8 +154,9 @@ namespace snapper
        const vector<string>& getIgnorePatterns() const { return ignore_patterns; }
 
        static list<ConfigInfo> getConfigs();
-       static void addConfig(const string& config_name, const string& subvolume,
-                             const string& fstype, const string& template_name);
+       static void createConfig(const string& config_name, const string& subvolume,
+                                const string& fstype, const string& template_name);
+       static void deleteConfig(const string& config_name);
 
        static bool detectFstype(const string& subvolume, string& fstype);
 
index 88e1a8737841ed3f1d33ff614f0468e6d92f48a3..89ce74ed8e83e55099b41dbc9daeced10a827086 100644 (file)
@@ -42,6 +42,7 @@
 
 #define CPBIN "/bin/cp"
 #define TOUCHBIN "/usr/bin/touch"
+#define RMBIN "/bin/rm"
 #define DIFFBIN "/usr/bin/diff"
 #define CHATTRBIN "/usr/bin/chattr"
 
index 23bfb4319a2eccb7c0e12e9d16fc0eb280f7ead4..c5233e3c5af2f7a5b85e5ded2d78464ab33652cb 100644 (file)
@@ -267,9 +267,9 @@ command_create_config()
 
     try
     {
-       Snapper::addConfig(config_name, subvolume, fstype, template_name);
+       Snapper::createConfig(config_name, subvolume, fstype, template_name);
     }
-    catch (const AddConfigFailedException& e)
+    catch (const CreateConfigFailedException& e)
     {
        cerr << sformat(_("Creating config failed (%s)."), e.what()) << endl;
        exit(EXIT_FAILURE);
@@ -277,6 +277,37 @@ command_create_config()
 }
 
 
+void
+help_delete_config()
+{
+    cout << _("  Delete config:") << endl
+        << _("\tsnapper delete-config") << endl
+        << endl;
+}
+
+
+void
+command_delete_config()
+{
+    getopts.parse("delete-config", GetOpts::no_options);
+    if (getopts.hasArgs())
+    {
+       cerr << _("Command 'delete-config' does not take arguments.") << endl;
+       exit(EXIT_FAILURE);
+    }
+
+    try
+    {
+       Snapper::deleteConfig(config_name);
+    }
+    catch (const DeleteConfigFailedException& e)
+    {
+       cerr << sformat(_("Deleting config failed (%s)."), e.what()) << endl;
+       exit(EXIT_FAILURE);
+    }
+}
+
+
 void
 help_list()
 {
@@ -1007,6 +1038,7 @@ command_help()
 
     help_list_configs();
     help_create_config();
+    help_delete_config();
     help_list();
     help_create();
     help_modify();
@@ -1063,6 +1095,7 @@ main(int argc, char** argv)
 
     cmds["list-configs"] = command_list_configs;
     cmds["create-config"] = command_create_config;
+    cmds["delete-config"] = command_delete_config;
     cmds["list"] = command_list;
     cmds["create"] = command_create;
     cmds["modify"] = command_modify;
@@ -1145,7 +1178,8 @@ main(int argc, char** argv)
        exit(EXIT_FAILURE);
     }
 
-    if (cmd->first == "help" || cmd->first == "list-configs" || cmd->first == "create-config")
+    if (cmd->first == "help" || cmd->first == "list-configs" ||
+       cmd->first == "create-config" || cmd->first == "delete-config")
     {
        (*cmd->second)();
     }