virtual ~Cleaner() {}
- void cleanup();
- void cleanup(std::function<bool()> condition);
+ void cleanup(Plugins::Report& report);
+ void cleanup(std::function<bool()> condition, Plugins::Report& report);
protected:
// snapshot but which is not included in tmp.
void filter_pre_post(ProxySnapshots& snapshots, list<ProxySnapshots::iterator>& tmp) const;
- void remove(const list<ProxySnapshots::iterator>& tmp);
+ void remove(const list<ProxySnapshots::iterator>& tmp, Plugins::Report& report);
// Should the cleanup with quota space be run?
bool is_quota_aware() const;
// Is the free space condition satisfied?
bool is_free_satisfied() const;
- void cleanup(ProxySnapshots& snapshots);
- void cleanup(ProxySnapshots& snapshots, std::function<bool()> condition);
+ void cleanup(ProxySnapshots& snapshots, Plugins::Report& report);
+ void cleanup(ProxySnapshots& snapshots, std::function<bool()> condition, Plugins::Report& report);
ProxySnapper* snapper;
void
-Cleaner::remove(const list<ProxySnapshots::iterator>& tmp)
+Cleaner::remove(const list<ProxySnapshots::iterator>& tmp, Plugins::Report& report)
{
for (list<ProxySnapshots::iterator>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
{
- snapper->deleteSnapshots({ *it }, verbose);
+ snapper->deleteSnapshots({ *it }, verbose, report);
}
}
void
-Cleaner::cleanup(ProxySnapshots& snapshots)
+Cleaner::cleanup(ProxySnapshots& snapshots, Plugins::Report& report)
{
list<ProxySnapshots::iterator> candidates = calculate_candidates(snapshots, Range::MAX);
filter(snapshots, candidates);
- remove(candidates);
+ remove(candidates, report);
}
void
-Cleaner::cleanup(ProxySnapshots& snapshots, std::function<bool()> condition)
+Cleaner::cleanup(ProxySnapshots& snapshots, std::function<bool()> condition, Plugins::Report& report)
{
while (!condition())
{
if (!tmp.empty())
{
- remove(tmp);
+ remove(tmp, report);
// after removing snapshots the condition must be reevaluated
break;
void
-Cleaner::cleanup()
+Cleaner::cleanup(Plugins::Report& report)
{
ProxySnapshots& snapshots = snapper->getSnapshots();
cout << "cleanup without condition" << '\n';
#endif
- cleanup(snapshots);
+ cleanup(snapshots, report);
if (is_quota_aware())
{
cout << "cleanup with quota condition" << '\n';
#endif
- cleanup(snapshots, std::bind(&Cleaner::is_quota_satisfied, this));
+ cleanup(snapshots, std::bind(&Cleaner::is_quota_satisfied, this), report);
}
else
{
cout << "cleanup with free condition" << '\n';
#endif
- cleanup(snapshots, std::bind(&Cleaner::is_free_satisfied, this));
+ cleanup(snapshots, std::bind(&Cleaner::is_free_satisfied, this), report);
}
else
{
void
-Cleaner::cleanup(std::function<bool()> condition)
+Cleaner::cleanup(std::function<bool()> condition, Plugins::Report& report)
{
ProxySnapshots& snapshots = snapper->getSnapshots();
cout << "cleanup with user condition" << '\n';
#endif
- cleanup(snapshots, condition);
+ cleanup(snapshots, condition, report);
}
void
-do_cleanup_number(ProxySnapper* snapper, bool verbose)
+do_cleanup_number(ProxySnapper* snapper, bool verbose, Plugins::Report& report)
{
NumberParameters parameters(snapper);
NumberCleaner cleaner(snapper, verbose, parameters);
- cleaner.cleanup();
+ cleaner.cleanup(report);
}
void
-do_cleanup_number(ProxySnapper* snapper, bool verbose, std::function<bool()> condition)
+do_cleanup_number(ProxySnapper* snapper, bool verbose, std::function<bool()> condition, Plugins::Report& report)
{
NumberParameters parameters(snapper);
NumberCleaner cleaner(snapper, verbose, parameters);
- cleaner.cleanup(condition);
+ cleaner.cleanup(condition, report);
}
void
-do_cleanup_timeline(ProxySnapper* snapper, bool verbose)
+do_cleanup_timeline(ProxySnapper* snapper, bool verbose, Plugins::Report& report)
{
TimelineParameters parameters(snapper);
TimelineCleaner cleaner(snapper, verbose, parameters);
- cleaner.cleanup();
+ cleaner.cleanup(report);
}
void
-do_cleanup_timeline(ProxySnapper* snapper, bool verbose, std::function<bool()> condition)
+do_cleanup_timeline(ProxySnapper* snapper, bool verbose, std::function<bool()> condition, Plugins::Report& report)
{
TimelineParameters parameters(snapper);
TimelineCleaner cleaner(snapper, verbose, parameters);
- cleaner.cleanup(condition);
+ cleaner.cleanup(condition, report);
}
void
-do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose)
+do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose, Plugins::Report& report)
{
EmptyPrePostParameters parameters(snapper);
EmptyPrePostCleaner cleaner(snapper, verbose, parameters);
- cleaner.cleanup();
+ cleaner.cleanup(report);
}
void
-do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose, std::function<bool()> condition)
+do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose, std::function<bool()> condition,
+ Plugins::Report& report)
{
EmptyPrePostParameters parameters(snapper);
EmptyPrePostCleaner cleaner(snapper, verbose, parameters);
- cleaner.cleanup(condition);
+ cleaner.cleanup(condition, report);
}
*/
void
-do_cleanup_number(ProxySnapper* snapper, bool verbose);
+do_cleanup_number(ProxySnapper* snapper, bool verbose, Plugins::Report& report);
void
-do_cleanup_timeline(ProxySnapper* snapper, bool verbose);
+do_cleanup_timeline(ProxySnapper* snapper, bool verbose, Plugins::Report& report);
void
-do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose);
+do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose, Plugins::Report& report);
/*
*/
void
-do_cleanup_number(ProxySnapper* snapper, bool verbose, std::function<bool()> condition);
+do_cleanup_number(ProxySnapper* snapper, bool verbose, std::function<bool()> condition,
+ Plugins::Report& report);
void
-do_cleanup_timeline(ProxySnapper* snapper, bool verbose, std::function<bool()> condition);
+do_cleanup_timeline(ProxySnapper* snapper, bool verbose, std::function<bool()> condition,
+ Plugins::Report& report);
void
-do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose, std::function<bool()> condition);
+do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose, std::function<bool()> condition,
+ Plugins::Report& report);
void
- run_cleanup(ProxySnapper* snapper, CleanupAlgorithm cleanup_algorithm, bool verbose)
+ run_cleanup(ProxySnapper* snapper, CleanupAlgorithm cleanup_algorithm, bool verbose, Plugins::Report& report)
{
switch (cleanup_algorithm)
{
case CleanupAlgorithm::NUMBER:
- do_cleanup_number(snapper, verbose);
+ do_cleanup_number(snapper, verbose, report);
break;
case CleanupAlgorithm::TIMELINE:
- do_cleanup_timeline(snapper, verbose);
+ do_cleanup_timeline(snapper, verbose, report);
break;
case CleanupAlgorithm::EMPTY_PRE_POST:
- do_cleanup_empty_pre_post(snapper, verbose);
+ do_cleanup_empty_pre_post(snapper, verbose, report);
break;
case CleanupAlgorithm::ALL:
- do_cleanup_number(snapper, verbose);
- do_cleanup_timeline(snapper, verbose);
- do_cleanup_empty_pre_post(snapper, verbose);
+ do_cleanup_number(snapper, verbose, report);
+ do_cleanup_timeline(snapper, verbose, report);
+ do_cleanup_empty_pre_post(snapper, verbose, report);
break;
}
}
void
run_cleanup(ProxySnapper* snapper, CleanupAlgorithm cleanup_algorithm, bool verbose,
- const FreeSpaceCondition& free_space_condition)
+ const FreeSpaceCondition& free_space_condition, Plugins::Report& report)
{
std::function<bool()> condition = [snapper, &free_space_condition]() {
return free_space_condition.is_satisfied(snapper);
switch (cleanup_algorithm)
{
case CleanupAlgorithm::NUMBER:
- do_cleanup_number(snapper, verbose, condition);
+ do_cleanup_number(snapper, verbose, condition, report);
break;
case CleanupAlgorithm::TIMELINE:
- do_cleanup_timeline(snapper, verbose, condition);
+ do_cleanup_timeline(snapper, verbose, condition, report);
break;
case CleanupAlgorithm::EMPTY_PRE_POST:
- do_cleanup_empty_pre_post(snapper, verbose, condition);
+ do_cleanup_empty_pre_post(snapper, verbose, condition, report);
break;
case CleanupAlgorithm::ALL:
- do_cleanup_number(snapper, verbose, condition);
- do_cleanup_timeline(snapper, verbose, condition);
- do_cleanup_empty_pre_post(snapper, verbose, condition);
+ do_cleanup_number(snapper, verbose, condition, report);
+ do_cleanup_timeline(snapper, verbose, condition, report);
+ do_cleanup_empty_pre_post(snapper, verbose, condition, report);
break;
}
}
void
- run_cleanup(const vector<ProxySnapper*>& snappers, CleanupAlgorithm cleanup_algorithm, bool verbose)
+ run_cleanup(const vector<ProxySnapper*>& snappers, CleanupAlgorithm cleanup_algorithm, bool verbose,
+ Plugins::Report& report)
{
for (ProxySnapper* snapper : snappers)
{
cout << "config " << snapper->configName() << '\n';
#endif
- run_cleanup(snapper, cleanup_algorithm, verbose);
+ run_cleanup(snapper, cleanup_algorithm, verbose, report);
}
}
void
run_cleanup(const vector<ProxySnapper*>& snappers, CleanupAlgorithm cleanup_algorithm, bool verbose,
- const FreeSpaceCondition& free_space_condition)
+ const FreeSpaceCondition& free_space_condition, Plugins::Report& report)
{
for (ProxySnapper* snapper : snappers)
{
try
{
- run_cleanup(snapper, cleanup_algorithm, verbose, free_space_condition);
+ run_cleanup(snapper, cleanup_algorithm, verbose, free_space_condition, report);
}
catch (...)
{
void
- command_cleanup(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*)
+ command_cleanup(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report)
{
const vector<Option> options = {
Option("path", required_argument),
if (free_space == 0)
{
- run_cleanup(snapper, cleanup_algorithm, global_options.verbose());
+ run_cleanup(snapper, cleanup_algorithm, global_options.verbose(), report);
}
else
{
if (!free_space_condition->is_satisfied())
{
- run_cleanup(snapper, cleanup_algorithm, global_options.verbose(), *free_space_condition);
+ run_cleanup(snapper, cleanup_algorithm, global_options.verbose(), *free_space_condition, report);
if (!free_space_condition->is_satisfied())
{
if (free_space == 0)
{
- run_cleanup(affected_snappers, cleanup_algorithm, global_options.verbose());
+ run_cleanup(affected_snappers, cleanup_algorithm, global_options.verbose(), report);
}
else
{
if (!free_space_condition->is_satisfied())
{
run_cleanup(affected_snappers, cleanup_algorithm, global_options.verbose(),
- *free_space_condition);
+ *free_space_condition, report);
if (!free_space_condition->is_satisfied())
{
void
- command_create_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*)
+ command_create_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report)
{
const vector<Option> options = {
Option("fstype", required_argument, 'f'),
exit(EXIT_FAILURE);
}
- snappers->createConfig(global_options.config(), subvolume, fstype, template_name);
+ snappers->createConfig(global_options.config(), subvolume, fstype, template_name, report);
}
}
void
- command_create(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_create(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("type", required_argument, 't'),
switch (type)
{
case CreateType::SINGLE: {
- snapshot1 = snapper->createSingleSnapshot(parent, scd);
+ snapshot1 = snapper->createSingleSnapshot(parent, scd, report);
if (print_number)
cout << snapshot1->getNum() << endl;
} break;
case CreateType::PRE: {
- snapshot1 = snapper->createPreSnapshot(scd);
+ snapshot1 = snapper->createPreSnapshot(scd, report);
if (print_number)
cout << snapshot1->getNum() << endl;
} break;
case CreateType::POST: {
- snapshot2 = snapper->createPostSnapshot(snapshot1, scd);
+ snapshot2 = snapper->createPostSnapshot(snapshot1, scd, report);
if (print_number)
cout << snapshot2->getNum() << endl;
} break;
case CreateType::PRE_POST: {
- snapshot1 = snapper->createPreSnapshot(scd);
+ snapshot1 = snapper->createPreSnapshot(scd, report);
system(command.c_str());
- snapshot2 = snapper->createPostSnapshot(snapshot1, scd);
+ snapshot2 = snapper->createPostSnapshot(snapshot1, scd, report);
if (print_number)
cout << snapshot1->getNum() << ".." << snapshot2->getNum() << endl;
} break;
void
- command_debug(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*)
+ command_debug(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report)
{
get_opts.parse("debug", GetOpts::no_options);
if (get_opts.has_args())
void
- command_delete_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*)
+ command_delete_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report)
{
get_opts.parse("delete-config", GetOpts::no_options);
if (get_opts.has_args())
exit(EXIT_FAILURE);
}
- snappers->deleteConfig(global_options.config());
+ snappers->deleteConfig(global_options.config(), report);
}
}
void
- command_delete(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_delete(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("sync", no_argument, 's')
filter_undeletables(snapshots, nums);
- snapper->deleteSnapshots(nums, global_options.verbose());
+ snapper->deleteSnapshots(nums, global_options.verbose(), report);
if (sync)
snapper->syncFilesystem();
void
- command_diff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_diff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("input", required_argument, 'i'),
void
- command_get_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_get_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("columns", required_argument)
void
- command_list_configs(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*)
+ command_list_configs(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report)
{
const vector<Option> options = {
Option("columns", required_argument)
void
- command_list(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper)
+ command_list(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("type", required_argument, 't'),
void
- command_modify(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_modify(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("description", required_argument, 'd'),
if (set_smd)
{
- snapper->modifySnapshot(snapshot, smd);
+ snapper->modifySnapshot(snapshot, smd, report);
}
if (set_read_only)
{
ProxyConfig config = snapper->getConfig();
const Filesystem* filesystem = get_filesystem(config, global_options.root());
- filesystem->setDefault(snapshot->getNum());
+ filesystem->setDefault(snapshot->getNum(), report);
}
}
}
void
- command_mount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_mount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
get_opts.parse("mount", GetOpts::no_options);
if (!get_opts.has_args())
#include <snapper/AppUtil.h>
#include <snapper/Filesystem.h>
-#include <snapper/Hooks.h>
+#include <snapper/PluginsImpl.h>
#include "utils/text.h"
#include "GlobalOptions.h"
void
- command_rollback(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_rollback(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper,
+ Plugins::Report& report)
{
const vector<Option> options = {
Option("print-number", no_argument, 'p'),
cout << _("Creating read-only snapshot of default subvolume.") << flush;
scd1.read_only = true;
- snapshot1 = snapper->createSingleSnapshotOfDefault(scd1);
+ snapshot1 = snapper->createSingleSnapshotOfDefault(scd1, report);
if (!global_options.quiet())
cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
scd2.description += sformat(" of #%d", active->getNum());
scd2.read_only = false;
- snapshot2 = snapper->createSingleSnapshot(snapshots.getCurrent(), scd2);
+ snapshot2 = snapper->createSingleSnapshot(snapshots.getCurrent(), scd2, report);
if (!global_options.quiet())
cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
if (!global_options.quiet())
cout << _("Creating read-only snapshot of current system.") << flush;
- snapshot1 = snapper->createSingleSnapshot(scd1);
+ snapshot1 = snapper->createSingleSnapshot(scd1, report);
if (!global_options.quiet())
cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
scd2.description += sformat(" of #%d", tmp->getNum());
scd2.read_only = false;
- snapshot2 = snapper->createSingleSnapshot(tmp, scd2);
+ snapshot2 = snapper->createSingleSnapshot(tmp, scd2, report);
if (!global_options.quiet())
cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
{
SMD smd = previous_default->getSmd();
smd.cleanup = "number";
- snapper->modifySnapshot(previous_default, smd);
+ snapper->modifySnapshot(previous_default, smd, report);
}
if (!global_options.quiet())
cout << sformat(_("Setting default subvolume to snapshot %d."), snapshot2->getNum()) << endl;
- filesystem->setDefault(snapshot2->getNum());
+ filesystem->setDefault(snapshot2->getNum(), report);
- Hooks::rollback(filesystem->snapshotDir(snapshot1->getNum()),
- filesystem->snapshotDir(snapshot2->getNum()));
- Hooks::rollback(Hooks::Stage::POST_ACTION, subvolume, filesystem, snapshot1->getNum(),
- snapshot2->getNum());
+ Plugins::rollback(filesystem->snapshotDir(snapshot1->getNum()),
+ filesystem->snapshotDir(snapshot2->getNum()), report);
+ Plugins::rollback(Plugins::Stage::POST_ACTION, subvolume, filesystem, snapshot1->getNum(),
+ snapshot2->getNum(), report);
if (print_number)
cout << snapshot2->getNum() << endl;
SMD smd = snapshot->getSmd();
smd.cleanup = "";
- snapper->modifySnapshot(snapshot, smd);
+ snapper->modifySnapshot(snapshot, smd, report);
if (!global_options.quiet())
cout << sformat(_("Setting default subvolume to snapshot %d."), snapshot->getNum()) << endl;
- filesystem->setDefault(snapshot->getNum());
+ filesystem->setDefault(snapshot->getNum(), report);
- Hooks::rollback(filesystem->snapshotDir(previous_default->getNum()),
- filesystem->snapshotDir(snapshot->getNum()));
- Hooks::rollback(Hooks::Stage::POST_ACTION, subvolume, filesystem, previous_default->getNum(),
- snapshot->getNum());
+ Plugins::rollback(filesystem->snapshotDir(previous_default->getNum()),
+ filesystem->snapshotDir(snapshot->getNum()), report);
+ Plugins::rollback(Plugins::Stage::POST_ACTION, subvolume, filesystem, previous_default->getNum(),
+ snapshot->getNum(), report);
}
break;
void
- command_set_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_set_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
get_opts.parse("set-config", GetOpts::no_options);
if (!get_opts.has_args())
void
- command_setup_quota(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_setup_quota(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
ParsedOpts opts = get_opts.parse("setup-quota", GetOpts::no_options);
if (get_opts.num_args() != 0)
void
- command_status(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_status(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("output", required_argument, 'o')
void
- command_umount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_umount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
get_opts.parse("umount", GetOpts::no_options);
if (!get_opts.has_args())
void
- command_undochange(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_undochange(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
const vector<Option> options = {
Option("input", required_argument, 'i')
void
- command_xadiff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*, ProxySnapper* snapper)
+ command_xadiff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers*,
+ ProxySnapper* snapper, Plugins::Report& report)
{
ParsedOpts opts = get_opts.parse("xadiff", GetOpts::no_options);
if (get_opts.num_args() < 1)
help_list_configs();
void
- command_list_configs(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*);
+ command_list_configs(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report);
void
help_create_config();
void
- command_create_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*);
+ command_create_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report);
void
help_delete_config();
void
- command_delete_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*);
+ command_delete_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report);
void
help_get_config();
void
- command_get_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*);
+ command_get_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report);
void
help_set_config();
void
- command_set_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*);
+ command_set_config(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report);
void
help_list();
void
- command_list(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper*);
+ command_list(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper*, Plugins::Report& report);
void
help_create();
void
- command_create(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_create(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
void
help_modify();
void
- command_modify(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_modify(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
void
help_delete();
void
- command_delete(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_delete(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
void
help_mount();
void
- command_mount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_mount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
void
help_umount();
void
- command_umount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_umount(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
void
help_status();
void
- command_status(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_status(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
void
help_diff();
void
- command_diff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_diff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
#ifdef ENABLE_XATTRS
help_xadiff();
void
- command_xadiff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_xadiff(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
#endif
help_undochange();
void
- command_undochange(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_undochange(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
#ifdef ENABLE_ROLLBACK
help_rollback();
void
- command_rollback(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_rollback(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
#endif
help_setup_quota();
void
- command_setup_quota(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_setup_quota(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
struct CleanupException : public Exception
help_cleanup();
void
- command_cleanup(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_cleanup(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
void
help_debug();
void
- command_debug(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers, ProxySnapper* snapper);
+ command_debug(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
+ ProxySnapper* snapper, Plugins::Report& report);
}
}
+vector<XReport>
+command_get_plugins_report(DBus::Connection& conn)
+{
+ DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "GetPluginsReport");
+
+ DBus::Message reply = conn.send_with_reply_and_block(call);
+
+ vector<XReport> xreport;
+
+ DBus::Unmarshaller unmarshaller(reply);
+ unmarshaller >> xreport;
+
+ return xreport;
+}
+
+
vector<string>
command_debug(DBus::Connection& conn)
{
void
command_sync(DBus::Connection& conn, const string& config_name);
+vector<XReport>
+command_get_plugins_report(DBus::Connection& conn);
+
vector<string>
command_debug(DBus::Connection& conn);
#include <snapper/SnapperDefines.h>
#include <snapper/Btrfs.h>
#include <snapper/FileUtils.h>
-#include <snapper/Hooks.h>
+#include <snapper/PluginsImpl.h>
#include "snapper/Log.h"
#include "utils/GetOpts.h"
using namespace std;
+Plugins::Report report;
+
+
void
step1(const string& device, const string& description, const string& cleanup,
const map<string, string>& userdata)
scd.cleanup = cleanup;
scd.userdata = userdata;
- Snapshots::iterator snapshot = snapper.createSingleSnapshot(scd);
+ Snapshots::iterator snapshot = snapper.createSingleSnapshot(scd, report);
cout << "again copying config-file" << endl;
cout << "setting default subvolume" << endl;
- snapshot->setDefault();
+ snapshot->setDefault(report);
cout << "done" << endl;
}
// preconditions (maybe incomplete):
// snapper rpms installed in chroot
- // all programs for snapper hooks installed in chroot
- // all preconditions for hooks satisfied
+ // all programs for snapper plugins installed in chroot
+ // all preconditions for plugins satisfied
cout << "step 4" << endl;
cout << "running external programs" << endl;
- Hooks::create_config(Hooks::Stage::POST_ACTION, "/", &btrfs);
+ Plugins::create_config(Plugins::Stage::POST_ACTION, "/", &btrfs, report);
cout << "done" << endl;
}
try
{
if (snapshot_type == "single") {
- snapshot = snapper.createSingleSnapshot(scd);
+ snapshot = snapper.createSingleSnapshot(scd, report);
} else if (snapshot_type == "pre") {
- snapshot = snapper.createPreSnapshot(scd);
+ snapshot = snapper.createPreSnapshot(scd, report);
} else if (snapshot_type == "post") {
Snapshots snapshots = snapper.getSnapshots();
Snapshots::iterator pre = snapshots.find(pre_num);
- snapshot = snapper.createPostSnapshot(pre, scd);
+ snapshot = snapper.createPostSnapshot(pre, scd, report);
}
}
catch (const runtime_error& e)
ProxySnapshots::const_iterator
-ProxySnapperDbus::createSingleSnapshot(const SCD& scd)
+ProxySnapperDbus::createSingleSnapshot(const SCD& scd, Plugins::Report& report)
{
unsigned int num = command_create_single_snapshot(conn(), config_name, scd.description,
scd.cleanup, scd.userdata);
ProxySnapshots::const_iterator
-ProxySnapperDbus::createSingleSnapshot(ProxySnapshots::const_iterator parent, const SCD& scd)
+ProxySnapperDbus::createSingleSnapshot(ProxySnapshots::const_iterator parent, const SCD& scd, Plugins::Report& report)
{
unsigned int num = command_create_single_snapshot_v2(conn(), config_name, parent->getNum(),
scd.read_only, scd.description, scd.cleanup,
ProxySnapshots::const_iterator
-ProxySnapperDbus::createSingleSnapshotOfDefault(const SCD& scd)
+ProxySnapperDbus::createSingleSnapshotOfDefault(const SCD& scd, Plugins::Report& report)
{
unsigned int num = command_create_single_snapshot_of_default(conn(), config_name, scd.read_only,
scd.description, scd.cleanup,
ProxySnapshots::const_iterator
-ProxySnapperDbus::createPreSnapshot(const SCD& scd)
+ProxySnapperDbus::createPreSnapshot(const SCD& scd, Plugins::Report& report)
{
unsigned int num = command_create_pre_snapshot(conn(), config_name, scd.description,
scd.cleanup, scd.userdata);
ProxySnapshots::const_iterator
-ProxySnapperDbus::createPostSnapshot(ProxySnapshots::const_iterator pre, const SCD& scd)
+ProxySnapperDbus::createPostSnapshot(ProxySnapshots::const_iterator pre, const SCD& scd, Plugins::Report& report)
{
unsigned int num = command_create_post_snapshot(conn(), config_name, pre->getNum(),
scd.description, scd.cleanup, scd.userdata);
void
-ProxySnapperDbus::modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd)
+ProxySnapperDbus::modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd, Plugins::Report& report)
{
command_set_snapshot(conn(), config_name, snapshot->getNum(), smd);
}
void
-ProxySnapperDbus::deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose)
+ProxySnapperDbus::deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose, Plugins::Report& report)
{
vector<unsigned int> nums;
for (const ProxySnapshots::iterator& proxy_snapshot : snapshots)
void
ProxySnappersDbus::createConfig(const string& config_name, const string& subvolume,
- const string& fstype, const string& template_name)
+ const string& fstype, const string& template_name, Plugins::Report& report)
{
command_create_config(conn, config_name, subvolume, fstype, template_name);
}
void
-ProxySnappersDbus::deleteConfig(const string& config_name)
+ProxySnappersDbus::deleteConfig(const string& config_name, Plugins::Report& report)
{
command_delete_config(conn, config_name);
}
}
+Plugins::Report
+ProxySnappersDbus::get_plugins_report() const
+{
+ Plugins::Report ret;
+
+ try
+ {
+ for (const XReport& xreport : command_get_plugins_report(conn))
+ ret.entries.emplace_back(xreport.name, xreport.args, xreport.exit_status);
+ }
+ catch (const DBus::ErrorException& e)
+ {
+ SN_CAUGHT(e);
+
+ // If snapper was just updated and the old snapperd is still
+ // running it might not know the GetPluginsReport method.
+
+ if (strcmp(e.name(), "error.unknown_method") != 0)
+ SN_RETHROW(e);
+ }
+
+ return ret;
+}
+
+
vector<string>
ProxySnappersDbus::debug() const
{
virtual ProxyConfig getConfig() const override;
virtual void setConfig(const ProxyConfig& proxy_config) override;
- virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd) override;
+ virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd, Plugins::Report& report) override;
virtual ProxySnapshots::const_iterator createSingleSnapshot(ProxySnapshots::const_iterator parent,
- const SCD& scd) override;
- virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd) override;
- virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd) override;
+ const SCD& scd, Plugins::Report& report) override;
+ virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd, Plugins::Report& report) override;
+ virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd, Plugins::Report& report) override;
virtual ProxySnapshots::const_iterator createPostSnapshot(ProxySnapshots::const_iterator pre,
- const SCD& scd) override;
+ const SCD& scd, Plugins::Report& report) override;
- virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd) override;
+ virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd, Plugins::Report& report) override;
- virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose) override;
+ virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose, Plugins::Report& report) override;
virtual ProxyComparison createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs,
bool mount) override;
{}
virtual void createConfig(const string& config_name, const string& subvolume,
- const string& fstype, const string& template_name) override;
+ const string& fstype, const string& template_name, Plugins::Report& report) override;
- virtual void deleteConfig(const string& config_name) override;
+ virtual void deleteConfig(const string& config_name, Plugins::Report& report) override;
virtual ProxySnapper* getSnapper(const string& config_name) override;
virtual map<string, ProxyConfig> getConfigs() const override;
+ virtual Plugins::Report get_plugins_report() const override;
+
virtual vector<string> debug() const override;
mutable DBus::Connection conn;
/*
- * Copyright (c) [2016-2020] SUSE LLC
+ * Copyright (c) [2016-2023] SUSE LLC
*
* All Rights Reserved.
*
ProxySnapshots::const_iterator
-ProxySnapperLib::createSingleSnapshot(const SCD& scd)
+ProxySnapperLib::createSingleSnapshot(const SCD& scd, Plugins::Report& report)
{
- proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshot(scd)));
+ proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshot(scd, report)));
return --proxy_snapshots.end();
}
ProxySnapshots::const_iterator
-ProxySnapperLib::createSingleSnapshot(ProxySnapshots::const_iterator parent, const SCD& scd)
+ProxySnapperLib::createSingleSnapshot(ProxySnapshots::const_iterator parent, const SCD& scd, Plugins::Report& report)
{
- proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshot(to_lib(*parent).it, scd)));
+ proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshot(to_lib(*parent).it, scd, report)));
return --proxy_snapshots.end();
}
ProxySnapshots::const_iterator
-ProxySnapperLib::createSingleSnapshotOfDefault(const SCD& scd)
+ProxySnapperLib::createSingleSnapshotOfDefault(const SCD& scd, Plugins::Report& report)
{
- proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshotOfDefault(scd)));
+ proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshotOfDefault(scd, report)));
return --proxy_snapshots.end();
}
ProxySnapshots::const_iterator
-ProxySnapperLib::createPreSnapshot(const SCD& scd)
+ProxySnapperLib::createPreSnapshot(const SCD& scd, Plugins::Report& report)
{
- proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createPreSnapshot(scd)));
+ proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createPreSnapshot(scd, report)));
return --proxy_snapshots.end();
}
ProxySnapshots::const_iterator
-ProxySnapperLib::createPostSnapshot(ProxySnapshots::const_iterator pre, const SCD& scd)
+ProxySnapperLib::createPostSnapshot(ProxySnapshots::const_iterator pre, const SCD& scd, Plugins::Report& report)
{
- proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createPostSnapshot(to_lib(*pre).it, scd)));
+ proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createPostSnapshot(to_lib(*pre).it, scd, report)));
return --proxy_snapshots.end();
}
void
-ProxySnapperLib::modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd)
+ProxySnapperLib::modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd, Plugins::Report& report)
{
- snapper->modifySnapshot(to_lib(*snapshot).it, smd);
+ snapper->modifySnapshot(to_lib(*snapshot).it, smd, report);
}
void
-ProxySnapperLib::deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose)
+ProxySnapperLib::deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose, Plugins::Report& report)
{
for (ProxySnapshots::iterator& snapshot : snapshots)
- snapper->deleteSnapshot(to_lib(*snapshot).it);
+ snapper->deleteSnapshot(to_lib(*snapshot).it, report);
ProxySnapshots& proxy_snapshots = getSnapshots();
for (ProxySnapshots::iterator& proxy_snapshot : snapshots)
void
ProxySnappersLib::createConfig(const string& config_name, const string& subvolume,
- const string& fstype, const string& template_name)
+ const string& fstype, const string& template_name, Plugins::Report& report)
{
- Snapper::createConfig(config_name, target_root, subvolume, fstype, template_name);
+ Snapper::createConfig(config_name, target_root, subvolume, fstype, template_name, report);
}
void
-ProxySnappersLib::deleteConfig(const string& config_name)
+ProxySnappersLib::deleteConfig(const string& config_name, Plugins::Report& report)
{
- Snapper::deleteConfig(config_name, target_root);
+ Snapper::deleteConfig(config_name, target_root, report);
}
virtual ProxyConfig getConfig() const override;
virtual void setConfig(const ProxyConfig& proxy_config) override;
- virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd) override;
+ virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd, Plugins::Report& report) override;
virtual ProxySnapshots::const_iterator createSingleSnapshot(ProxySnapshots::const_iterator parent,
- const SCD& scd) override;
- virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd) override;
- virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd) override;
+ const SCD& scd, Plugins::Report& report) override;
+ virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd, Plugins::Report& report) override;
+ virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd, Plugins::Report& report) override;
virtual ProxySnapshots::const_iterator createPostSnapshot(ProxySnapshots::const_iterator pre,
- const SCD& scd) override;
+ const SCD& scd, Plugins::Report& report) override;
- virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd) override;
+ virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd, Plugins::Report& report) override;
- virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose) override;
+ virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose, Plugins::Report& report) override;
virtual ProxyComparison createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs,
bool mount) override;
: target_root(target_root)
{}
- virtual void createConfig(const string& config_name, const string& subvolume,
- const string& fstype, const string& template_name) override;
+ virtual void createConfig(const string& config_name, const string& subvolume, const string& fstype,
+ const string& template_name, Plugins::Report& report) override;
- virtual void deleteConfig(const string& config_name) override;
+ virtual void deleteConfig(const string& config_name, Plugins::Report& report) override;
virtual ProxySnapper* getSnapper(const string& config_name) override;
virtual map<string, ProxyConfig> getConfigs() const override;
+ virtual Plugins::Report get_plugins_report() const override { return {}; }
+
virtual vector<string> debug() const override { return Snapper::debug(); }
private:
virtual ProxyConfig getConfig() const = 0;
virtual void setConfig(const ProxyConfig& proxy_config) = 0;
- virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd) = 0;
+ virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd, Plugins::Report& report) = 0;
virtual ProxySnapshots::const_iterator createSingleSnapshot(ProxySnapshots::const_iterator parent,
- const SCD& scd) = 0;
- virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd) = 0;
- virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd) = 0;
+ const SCD& scd, Plugins::Report& report) = 0;
+ virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd, Plugins::Report& report) = 0;
+ virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd, Plugins::Report& report) = 0;
virtual ProxySnapshots::const_iterator createPostSnapshot(ProxySnapshots::const_iterator pre,
- const SCD& scd) = 0;
+ const SCD& scd, Plugins::Report& report) = 0;
- virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd) = 0;
+ virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd, Plugins::Report& report) = 0;
- virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose) = 0;
+ virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose, Plugins::Report& report) = 0;
virtual ProxyComparison createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs,
bool mount) = 0;
static ProxySnappers createLib(const string& target_root);
void createConfig(const string& config_name, const string& subvolume, const string& fstype,
- const string& template_name)
- { return impl->createConfig(config_name, subvolume, fstype, template_name); }
+ const string& template_name, Plugins::Report& report)
+ { return impl->createConfig(config_name, subvolume, fstype, template_name, report); }
- void deleteConfig(const string& config_name)
- { return impl->deleteConfig(config_name); }
+ void deleteConfig(const string& config_name, Plugins::Report& report)
+ { return impl->deleteConfig(config_name, report); }
ProxySnapper* getSnapper(const string& config_name)
{ return impl->getSnapper(config_name); }
map<string, ProxyConfig> getConfigs() const
{ return impl->getConfigs(); }
+ /**
+ * This function needs a few works: The Snapper class does not have a Plugin::Report
+ * object. The individual functions of the Snapper class have. For for proxy-lib this
+ * call is a no-op. For proxy-dbus the server is queried which has a per client
+ * Plugin::Report object.
+ */
+ Plugins::Report get_plugins_report() const
+ { return impl->get_plugins_report(); }
+
vector<string> debug() const
{ return impl->debug(); }
virtual ~Impl() {}
virtual void createConfig(const string& config_name, const string& subvolume,
- const string& fstype, const string& template_name) = 0;
+ const string& fstype, const string& template_name, Plugins::Report& report) = 0;
- virtual void deleteConfig(const string& config_name) = 0;
+ virtual void deleteConfig(const string& config_name, Plugins::Report& report) = 0;
virtual ProxySnapper* getSnapper(const string& config_name) = 0;
virtual map<string, ProxyConfig> getConfigs() const = 0;
+ virtual Plugins::Report get_plugins_report() const = 0;
+
virtual vector<string> debug() const = 0;
};
#include <cstdlib>
#include <cstring>
#include <iostream>
+#include <boost/algorithm/string.hpp>
#include <snapper/Snapper.h>
#include <snapper/SnapperTmpl.h>
struct Cmd
{
typedef void (*cmd_func_t)(GlobalOptions& global_options, GetOpts& get_opts, ProxySnappers* snappers,
- ProxySnapper* snapper);
+ ProxySnapper* snapper, Plugins::Report& report);
typedef void (*help_func_t)();
Cmd("debug", command_debug, help_debug, false)
};
+ int exit_status = EXIT_SUCCESS;
+
try
{
GetOpts get_opts(argc, argv);
y2mil("executing command");
+ Plugins::Report client_report;
+
if (cmd->needs_snapper)
- (*cmd->cmd_func)(global_options, get_opts, &snappers, snappers.getSnapper(global_options.config()));
+ (*cmd->cmd_func)(global_options, get_opts, &snappers, snappers.getSnapper(global_options.config()),
+ client_report);
else
- (*cmd->cmd_func)(global_options, get_opts, &snappers, nullptr);
+ (*cmd->cmd_func)(global_options, get_opts, &snappers, nullptr, client_report);
+
+ Plugins::Report server_report = snappers.get_plugins_report();
+
+ // Plugins can be started from the client or server. So we have to check both
+ // reports.
+
+ for (const Plugins::Report::Entry& entry : client_report.entries)
+ {
+ y2deb("client: " << entry.name << " " << boost::join(entry.args, " ") << " exit-status: " <<
+ entry.exit_status);
+
+ if (entry.exit_status != 0)
+ {
+ cerr << sformat(_("Client-side plugin '%s' failed."), entry.name.c_str()) << '\n';
+ exit_status = EXIT_FAILURE;
+ }
+ }
+
+ for (const Plugins::Report::Entry& entry : server_report.entries)
+ {
+ y2deb("server: " << entry.name << " " << boost::join(entry.args, " ") << " exit-status: " <<
+ entry.exit_status);
+
+ if (entry.exit_status != 0)
+ {
+ cerr << sformat(_("Server-side plugin '%s' failed."), entry.name.c_str()) << '\n';
+ exit_status = EXIT_FAILURE;
+ }
+ }
}
catch (const DBus::ErrorException& e)
{
exit(EXIT_FAILURE);
}
- exit(EXIT_SUCCESS);
+ y2deb("exit-status: " << exit_status);
+ exit(exit_status);
}
/*
* Copyright (c) [2014-2015] Novell, Inc.
- * Copyright (c) [2016-2020] SUSE LLC
+ * Copyright (c) [2016-2023] SUSE LLC
*
* All Rights Reserved.
*
#include "config.h"
-#include <stdlib.h>
+#include <cstdlib>
#include <iostream>
#include "utils/text.h"
// snapper-<name>.service'.
+Plugins::Report report;
+
+
bool
call_with_error_check(std::function<void()> func)
{
scd.cleanup = "timeline";
scd.userdata = userdata;
- if (!call_with_error_check([snapper, scd](){ snapper->createSingleSnapshot(scd); }))
+ if (!call_with_error_check([snapper, scd](){ snapper->createSingleSnapshot(scd, report); }))
{
cerr << "timeline for '" << value.first << "' failed." << endl;
ok = false;
{
cout << "running number cleanup for '" << value.first << "'." << endl;
- if (!call_with_error_check([snapper](){ do_cleanup_number(snapper, false); }))
+ if (!call_with_error_check([snapper](){ do_cleanup_number(snapper, false, report); }))
{
cerr << "number cleanup for '" << value.first << "' failed." << endl;
ok = false;
{
cout << "running timeline cleanup for '" << value.first << "'." << endl;
- if (!call_with_error_check([snapper](){ do_cleanup_timeline(snapper, false); }))
+ if (!call_with_error_check([snapper](){ do_cleanup_timeline(snapper, false, report); }))
{
cerr << "timeline cleanup for '" << value.first << "' failed." << endl;
ok = false;
{
cout << "running empty-pre-post cleanup for '" << value.first << "'." << endl;
- if (!call_with_error_check([snapper](){ do_cleanup_empty_pre_post(snapper, false); }))
+ if (!call_with_error_check([snapper](){ do_cleanup_empty_pre_post(snapper, false, report); }))
{
cerr << "empty-pre-post cleanup for " << value.first << " failed." << endl;
ok = false;
ok = false;
}
+ for (const Plugins::Report::Entry& entry : report.entries)
+ {
+ if (entry.exit_status != 0)
+ {
+ cerr << "server-side plugin '" << entry.name << "' failed\n";
+ ok = false;
+ }
+ }
+
exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
/*
* Copyright (c) 2012 Novell, Inc.
- * Copyright (c) [2016,2018] SUSE LLC
+ * Copyright (c) [2016-2023] SUSE LLC
*
* All Rights Reserved.
*
const char* TypeInfo<XConfigInfo>::signature = "(ssa{ss})";
const char* TypeInfo<XSnapshot>::signature = "(uquxussa{ss})";
const char* TypeInfo<XFile>::signature = "(su)";
+ const char* TypeInfo<XReport>::signature = "(sasi)";
Unmarshaller&
{
unmarshaller.open_recurse();
unmarshaller >> data.num >> data.type >> data.pre_num >> data.date >> data.uid >> data.description
- >> data.cleanup >> data.userdata;
+ >> data.cleanup >> data.userdata;
unmarshaller.close_recurse();
return unmarshaller;
}
return marshaller;
}
+
+ Unmarshaller&
+ operator>>(Unmarshaller& unmarshaller, XReport& data)
+ {
+ unmarshaller.open_recurse();
+ unmarshaller >> data.name >> data.args >> data.exit_status;
+ unmarshaller.close_recurse();
+ return unmarshaller;
+ }
+
}
/*
* Copyright (c) 2012 Novell, Inc.
- * Copyright (c) [2016,2018] SUSE LLC
+ * Copyright (c) [2016-2023] SUSE LLC
*
* All Rights Reserved.
*
};
+struct XReport
+{
+ string name;
+ vector<string> args;
+ int exit_status;
+};
+
+
namespace DBus
{
template <> struct TypeInfo<XSnapshot> { static const char* signature; };
template <> struct TypeInfo<XConfigInfo> { static const char* signature; };
template <> struct TypeInfo<XFile> { static const char* signature; };
+ template <> struct TypeInfo<XReport> { static const char* signature; };
Unmarshaller& operator>>(Unmarshaller& unmarshaller, XConfigInfo& data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, FreeSpaceData& data);
+ Unmarshaller& operator>>(Unmarshaller& unmarshaller, XReport& data);
+
}
CapabilityBoundingSet=CAP_DAC_OVERRIDE is needed for directory
comparison (in some cases) - but not if using btrfs send/receive.
-Finally do not forget the hooks.
+Finally do not forget the plugins.
Have a lot of fun...
<refentry id='snapper8' xmlns:xlink="http://www.w3.org/1999/xlink">
<refentryinfo>
- <date>2023-04-19</date>
+ <date>2023-11-28</date>
</refentryinfo>
<refmeta>
<refentrytitle>snapper</refentrytitle>
<manvolnum>8</manvolnum>
- <refmiscinfo class='date'>2023-04-19</refmiscinfo>
+ <refmiscinfo class='date'>2023-11-28</refmiscinfo>
<refmiscinfo class='version'>@VERSION@</refmiscinfo>
<refmiscinfo class='manual'>Filesystem Snapshot Management</refmiscinfo>
</refmeta>
</variablelist>
</refsect1>
+ <refsect1 id='exit_status'>
+ <title>EXIT STATUS</title>
+ <para>Normally the exit status is 0. If an error occured the exit status is
+ 1. It is also an error if the exit status of a plugin is not 0.</para>
+ </refsect1>
+
<refsect1 id='notes'>
<title>NOTES</title>
<para>There is no mechanism to ensure consistency of the files while a
+-------------------------------------------------------------------
+Tue Nov 28 08:22:41 CET 2023 - aschnell@suse.com
+
+- report plugin failures (gh#openSUSE/snapper#846)
+
-------------------------------------------------------------------
Wed Nov 22 16:15:37 CET 2023 - aschnell@suse.com