\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.
+-------------------------------------------------------------------
+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
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");
}
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);
{
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");
}
}
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;
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;
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;
}
catch (const FileNotFoundException& e)
{
- throw ListConfigsFailedException("sysconfig file not found");
+ throw ListConfigsFailedException("sysconfig-file not found");
}
return config_infos;
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();
{
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;
}
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
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);
}
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
}
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");
+ }
}
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;
};
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);
#define CPBIN "/bin/cp"
#define TOUCHBIN "/usr/bin/touch"
+#define RMBIN "/bin/rm"
#define DIFFBIN "/usr/bin/diff"
#define CHATTRBIN "/usr/bin/chattr"
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);
}
+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()
{
help_list_configs();
help_create_config();
+ help_delete_config();
help_list();
help_create();
help_modify();
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;
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)();
}