From: Arvin Schnell Date: Fri, 23 Dec 2011 14:33:35 +0000 (+0100) Subject: - allow to delete a configuration X-Git-Tag: v0.1.3~255 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6065e0948b33293fe13dd220d6665d96387804ad;p=thirdparty%2Fsnapper.git - allow to delete a configuration --- diff --git a/doc/snapper.8.in b/doc/snapper.8.in index 499fcccc..5ecee0b1 100644 --- a/doc/snapper.8.in +++ b/doc/snapper.8.in @@ -121,6 +121,12 @@ this option snapper detect the filesystem. \fI\-t, \-\-template\fR 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. diff --git a/package/snapper.changes b/package/snapper.changes index 0f88d5b7..96460b74 100644 --- a/package/snapper.changes +++ b/package/snapper.changes @@ -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 diff --git a/snapper/Filesystem.cc b/snapper/Filesystem.cc index b5b09cbe..3839608d 100644 --- a/snapper/Filesystem.cc +++ b/snapper/Filesystem.cc @@ -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"); } } diff --git a/snapper/Filesystem.h b/snapper/Filesystem.h index c5ff827f..0c44d66a 100644 --- a/snapper/Filesystem.h +++ b/snapper/Filesystem.h @@ -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; diff --git a/snapper/Snapper.cc b/snapper/Snapper.cc index 0425f2a3..a009324e 100644 --- a/snapper/Snapper.cc +++ b/snapper/Snapper.cc @@ -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 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; @@ -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(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 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"); + } } diff --git a/snapper/Snapper.h b/snapper/Snapper.h index 6b234904..f640f679 100644 --- a/snapper/Snapper.h +++ b/snapper/Snapper.h @@ -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& getIgnorePatterns() const { return ignore_patterns; } static list 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); diff --git a/snapper/SnapperDefines.h b/snapper/SnapperDefines.h index 88e1a873..89ce74ed 100644 --- a/snapper/SnapperDefines.h +++ b/snapper/SnapperDefines.h @@ -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" diff --git a/tools/snapper.cc b/tools/snapper.cc index 23bfb431..c5233e3c 100644 --- a/tools/snapper.cc +++ b/tools/snapper.cc @@ -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)(); }