Correct order of going throu backups, classify code
parent
e7e83723e6
commit
b81cf9805f
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
|
||||
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
|
||||
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug",
|
||||
"program": "${command:cmake.launchTargetPath}",
|
||||
"args": ["workstation"],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
307
main.cpp
307
main.cpp
|
|
@ -14,6 +14,7 @@
|
|||
#include <boost/asio.hpp>
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
|
|
@ -24,107 +25,160 @@ namespace asio = boost::asio;
|
|||
namespace po = boost::program_options;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
bool dry_run = false;
|
||||
|
||||
template<int keep_every_x_days,int till_y_day>std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
class zfsbackupcleaner
|
||||
{
|
||||
if(ct == times.rend())
|
||||
return ct;
|
||||
|
||||
boost::posix_time::time_duration dur;
|
||||
boost::posix_time::ptime last_kept_time;
|
||||
|
||||
while( ct != times.rend() && (dur = now - *ct).hours() <= till_y_day * 24)
|
||||
public:
|
||||
zfsbackupcleaner(std::string backupsystem): _backupsystem(backupsystem), _now(boost::posix_time::second_clock::local_time()), _dry_run(false)
|
||||
{
|
||||
last_kept_time = *ct;
|
||||
std::cout << "Keeping Backup " << last_kept_time << " of this day." << std::endl << std::endl;
|
||||
ct++;
|
||||
std::cout << "Gehe aus von aktueller Zeit: " << _now << std::endl << std::endl;
|
||||
}
|
||||
|
||||
while( ct != times.rend() && (dur = last_kept_time - *ct).hours() < keep_every_x_days * 24)
|
||||
void set_dry_run(bool val = true) { _dry_run = val; }
|
||||
|
||||
void read_backups()
|
||||
{
|
||||
asio::io_context ctx;
|
||||
asio::readable_pipe out(ctx);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), {"list", "-t", "snapshot", "/backup/"+_backupsystem}, bp::process_stdio{{/* in to default*/}, out, {/* err to default */}});
|
||||
|
||||
std::string output;
|
||||
|
||||
boost::system::error_code ec;
|
||||
asio::read(out, asio::dynamic_buffer(output), ec);
|
||||
assert(!ec || (ec==asio::error::eof));
|
||||
proc.wait();
|
||||
|
||||
std::stringstream lines(output);
|
||||
|
||||
for(std::string line; std::getline(lines, line);)
|
||||
{
|
||||
if(ct == --times.rend())
|
||||
std::string::size_type pos = line.find(' ');
|
||||
line = line.substr(0,pos);
|
||||
//std::cout << "X: " << line << std::endl;
|
||||
|
||||
if(line == "NAME")
|
||||
continue;
|
||||
|
||||
pos = line.find('@');
|
||||
_backupbase = line.substr(0,pos);
|
||||
std::string timestring = line.substr(pos+1);
|
||||
timestring[10]=' ';
|
||||
timestring[13]=':';
|
||||
timestring[16]=':';
|
||||
boost::posix_time::ptime t(boost::posix_time::time_from_string(timestring));
|
||||
|
||||
_backuptimes.insert(t);
|
||||
}
|
||||
}
|
||||
|
||||
void clean_backups ()
|
||||
{
|
||||
if(_backuptimes.empty())
|
||||
{
|
||||
std::cout << "Keine Backups für >" << _backupsystem << "< gefunden." << std::endl << "Keine weitere Behandlung." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if(_backuptimes.size() < 7)
|
||||
{
|
||||
std::cout << "Weniger als 7 Backups für >" << _backupsystem << "< gefunden." << std::endl << "Keine weitere Behandlung." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Hinweis: Die Backups werden so von "zfs list" übermittelt, dass das älteste am Anfang steht und das jüngste am Ende der Liste
|
||||
|
||||
_iter_current=_backuptimes.begin();
|
||||
_iter_last_to_handle = _backuptimes.end();
|
||||
std::advance(_iter_last_to_handle, -7); // Die letzten sieben Backups werden besonders behandelt - sie bleiben in jedem Fall erhalten!
|
||||
|
||||
// Nun von hinten her die Backups durchgehen
|
||||
|
||||
// A) Das allererste Backup behalten wir in jedem Fall
|
||||
std::cout << "Behalte allererstes Backup " << *_iter_current << " in diesem Backup-Set." << std::endl << std::endl;
|
||||
_iter_current++;
|
||||
|
||||
// B) after 365 days, we keep one backup every 30 days
|
||||
handle_backups<30,365>();
|
||||
|
||||
// C) after 30 days, we keep one backup every 7 days
|
||||
handle_backups<7,30>();
|
||||
|
||||
// D) after one day, we keep one backup per day
|
||||
handle_backups<1,1>();
|
||||
|
||||
// E) Behalte die letzten bis zu sieben Backups
|
||||
for(; _iter_current != _backuptimes.end(); _iter_current++)
|
||||
{
|
||||
|
||||
std::cout << "Behalte Backup " << *_iter_current << ", weil es zu den letzten 7 gehört." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<int keep_every_x_days,int after_y_day> void handle_backups()
|
||||
{
|
||||
if(_iter_current == _iter_last_to_handle)
|
||||
return;
|
||||
|
||||
boost::gregorian::date_duration dur;
|
||||
boost::posix_time::ptime last_kept_time;
|
||||
|
||||
while( _iter_current != _iter_last_to_handle && (dur = _now.date() - _iter_current->date()) > boost::gregorian::days(after_y_day))
|
||||
{
|
||||
last_kept_time = *_iter_current;
|
||||
std::cout << "Behalte Backup " << last_kept_time << " [Älter als " << after_y_day << ", Backup alle " << keep_every_x_days << " Tage behalten]." << std::endl << std::endl;
|
||||
_iter_current++;
|
||||
|
||||
while( _iter_current != _iter_last_to_handle && (dur = _iter_current->date() - last_kept_time.date()) < boost::gregorian::days(keep_every_x_days))
|
||||
{
|
||||
std::cout << "Keeping last Backup " << *ct << " in this backup-set." << std::endl << std::endl;
|
||||
return ct++;
|
||||
std::cout << "Entferne Backup " << *_iter_current << " weil wir bereits eines im aktuellen Zyklus haben [Älter als " << after_y_day << ", Backup alle " << keep_every_x_days << " Tage behalten]." << std::endl;
|
||||
|
||||
if(!_dry_run)
|
||||
{
|
||||
std::string timestring = boost::posix_time::to_iso_extended_string(*_iter_current);
|
||||
timestring[10]='_';
|
||||
timestring[13]='-';
|
||||
timestring[16]='-';
|
||||
timestring=timestring.substr(0, 19);
|
||||
|
||||
asio::io_context ctx;
|
||||
asio::readable_pipe out(ctx);
|
||||
|
||||
std::vector<std::string> args;
|
||||
args.push_back("destroy");
|
||||
args.push_back("-v");
|
||||
if(_dry_run)
|
||||
args.push_back("-n");
|
||||
args.push_back(_backupbase + "@" + timestring);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), args, bp::process_stdio{{/* in to default*/}, out, {/* err to default */}});
|
||||
|
||||
std::string output;
|
||||
|
||||
boost::system::error_code ec;
|
||||
asio::read(out, asio::dynamic_buffer(output), ec);
|
||||
assert(!ec || (ec==asio::error::eof));
|
||||
proc.wait();
|
||||
|
||||
std::cout << output << std::endl;
|
||||
}
|
||||
_iter_current++;
|
||||
}
|
||||
|
||||
std::cout << "Removing Backup " << *ct << " because we have already one in the relevant set of keeping every " << keep_every_x_days << " till " << till_y_day << " days." << std::endl;
|
||||
|
||||
std::string timestring = boost::posix_time::to_iso_extended_string(*ct);
|
||||
timestring[10]='_';
|
||||
timestring[13]='-';
|
||||
timestring[16]='-';
|
||||
timestring=timestring.substr(0, 19);
|
||||
|
||||
asio::io_context ctx;
|
||||
asio::readable_pipe out(ctx);
|
||||
|
||||
std::vector<std::string> args;
|
||||
args.push_back("destroy");
|
||||
args.push_back("-v");
|
||||
if(dry_run)
|
||||
args.push_back("-n");
|
||||
args.push_back(snapshotbase + "@" + timestring);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), args, bp::process_stdio{{/* in to default*/}, out, {/* err to default */}});
|
||||
|
||||
std::string output;
|
||||
|
||||
boost::system::error_code ec;
|
||||
asio::read(out, asio::dynamic_buffer(output), ec);
|
||||
assert(!ec || (ec==asio::error::eof));
|
||||
proc.wait();
|
||||
|
||||
std::cout << output << std::endl;
|
||||
|
||||
ct++;
|
||||
}
|
||||
}
|
||||
|
||||
return ct;
|
||||
}
|
||||
std::string _backupsystem;
|
||||
boost::posix_time::ptime _now;
|
||||
bool _dry_run;
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after_one_day(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
{
|
||||
// after one day, we keep one backup per day
|
||||
|
||||
return handle_backups_after<1,30>(snapshotbase, times, ct, now);
|
||||
|
||||
/*if(ct == times.rend())
|
||||
return ct;
|
||||
|
||||
boost::posix_time::time_duration dur;
|
||||
boost::posix_time::ptime last_kept_time;
|
||||
|
||||
while( ct != times.rend() && (dur = now - *ct).hours() <= 30 * 24)
|
||||
{
|
||||
last_kept_time = *ct;
|
||||
std::cout << "Keeping Backup " << last_kept_time << " of this day." << std::endl;
|
||||
ct++;
|
||||
|
||||
while( ct != times.rend() && (dur = last_kept_time - *ct).hours() < 24)
|
||||
{
|
||||
std::cout << "Removing Backup " << *ct << " because we have already one in 24 hours." << std::endl;
|
||||
ct++;
|
||||
}
|
||||
}
|
||||
|
||||
return ct;*/
|
||||
}
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after_30_days(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
{
|
||||
// after 30 days, we keep one backup every 7 days
|
||||
|
||||
return handle_backups_after<7,365>(snapshotbase, times, ct, now);
|
||||
}
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after_365_days(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
{
|
||||
// after 365 days, we keep one backup every 30 days
|
||||
|
||||
return handle_backups_after<30, 365*100>(snapshotbase, times, ct, now);
|
||||
}
|
||||
std::string _backupbase;
|
||||
std::set<boost::posix_time::ptime> _backuptimes;
|
||||
std::set<boost::posix_time::ptime>::iterator _iter_current;
|
||||
std::set<boost::posix_time::ptime>::iterator _iter_last_to_handle;
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
|
@ -156,10 +210,7 @@ int main(int argc, char** argv){
|
|||
std::cout << options << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(vm.count("dry-run"))
|
||||
dry_run = true;
|
||||
|
||||
|
||||
std::string backupsystem = vm["backupsystem"].as<std::string>();
|
||||
|
||||
if(backupsystem != "workstation" && ! fs::exists("/backup/"+backupsystem))
|
||||
|
|
@ -168,72 +219,14 @@ int main(int argc, char** argv){
|
|||
return -1;
|
||||
}
|
||||
|
||||
asio::io_context ctx;
|
||||
asio::readable_pipe out(ctx);
|
||||
zfsbackupcleaner zbc(backupsystem);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), {"list", "-t", "snapshot", "/backup/"+backupsystem}, bp::process_stdio{{/* in to default*/}, out, {/* err to default */}});
|
||||
if(vm.count("dry-run"))
|
||||
zbc.set_dry_run(true);
|
||||
|
||||
std::string output;
|
||||
|
||||
boost::system::error_code ec;
|
||||
asio::read(out, asio::dynamic_buffer(output), ec);
|
||||
assert(!ec || (ec==asio::error::eof));
|
||||
proc.wait();
|
||||
|
||||
//std::cout << "OUTPUT" << output << "END" << std::endl;
|
||||
|
||||
std::stringstream lines(output);
|
||||
|
||||
std::set<boost::posix_time::ptime> times;
|
||||
|
||||
std::string snapshotbase;
|
||||
|
||||
for(std::string line; std::getline(lines, line);)
|
||||
{
|
||||
std::string::size_type pos = line.find(' ');
|
||||
line = line.substr(0,pos);
|
||||
//std::cout << "X: " << line << std::endl;
|
||||
|
||||
if(line == "NAME")
|
||||
continue;
|
||||
|
||||
pos = line.find('@');
|
||||
snapshotbase = line.substr(0,pos);
|
||||
std::string timestring = line.substr(pos+1);
|
||||
timestring[10]=' ';
|
||||
timestring[13]=':';
|
||||
timestring[16]=':';
|
||||
boost::posix_time::ptime t(boost::posix_time::time_from_string(timestring));
|
||||
|
||||
times.insert(t);
|
||||
}
|
||||
|
||||
if(times.empty())
|
||||
{
|
||||
std::cout << "NO SNAPSHOTS FOUND — EXIT";
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator current_time = times.rbegin();
|
||||
|
||||
// handle fist 24 hours!!!
|
||||
|
||||
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
|
||||
|
||||
std::cout << "Gehe aus von aktueller Zeit: " << now << std::endl << std::endl;
|
||||
|
||||
boost::posix_time::time_duration dur;
|
||||
zbc.read_backups();
|
||||
|
||||
while( (dur = now - *current_time).hours() <= 72)
|
||||
{
|
||||
std::cout << "Omitting Backup " << *current_time << " because it is too young to handle (" << dur.hours() << " hours old)." << std::endl;
|
||||
current_time++;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
zbc.clean_backups();
|
||||
|
||||
current_time = handle_backups_after_one_day(snapshotbase, times, current_time, now);
|
||||
current_time = handle_backups_after_30_days(snapshotbase, times, current_time, now);
|
||||
current_time = handle_backups_after_365_days(snapshotbase, times, current_time, now);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,242 @@
|
|||
// ACHTUNG: Die Backups müssen von hinten her, also vor ersten Backup aus, bis NOW durchgegangen werden, nicht umgekehrt!!!
|
||||
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time_config.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/date_time/posix_time/time_formatters.hpp>
|
||||
#include <boost/date_time/posix_time/time_parsers.hpp>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <boost/program_options/positional_options.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/process.hpp>
|
||||
#include <boost/process/v2/stdio.hpp>
|
||||
#include <boost/process/v2/environment.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <set>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace bp = boost::process;
|
||||
namespace asio = boost::asio;
|
||||
namespace po = boost::program_options;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
bool dry_run = false;
|
||||
|
||||
template<int keep_every_x_days,int till_y_day>std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
{
|
||||
if(ct == times.rend())
|
||||
return ct;
|
||||
|
||||
boost::posix_time::time_duration dur;
|
||||
boost::posix_time::ptime last_kept_time;
|
||||
|
||||
while( ct != times.rend() && (dur = now - *ct).hours() <= till_y_day * 24)
|
||||
{
|
||||
last_kept_time = *ct;
|
||||
std::cout << "Keeping Backup " << last_kept_time << " of this day." << std::endl << std::endl;
|
||||
ct++;
|
||||
|
||||
while( ct != times.rend() && (dur = last_kept_time - *ct).hours() < keep_every_x_days * 24)
|
||||
{
|
||||
if(ct == --times.rend())
|
||||
{
|
||||
std::cout << "Keeping last Backup " << *ct << " in this backup-set." << std::endl << std::endl;
|
||||
return ct++;
|
||||
}
|
||||
|
||||
std::cout << "Removing Backup " << *ct << " because we have already one in the relevant set of keeping every " << keep_every_x_days << " till " << till_y_day << " days." << std::endl;
|
||||
|
||||
std::string timestring = boost::posix_time::to_iso_extended_string(*ct);
|
||||
timestring[10]='_';
|
||||
timestring[13]='-';
|
||||
timestring[16]='-';
|
||||
timestring=timestring.substr(0, 19);
|
||||
|
||||
asio::io_context ctx;
|
||||
asio::readable_pipe out(ctx);
|
||||
|
||||
std::vector<std::string> args;
|
||||
args.push_back("destroy");
|
||||
args.push_back("-v");
|
||||
if(dry_run)
|
||||
args.push_back("-n");
|
||||
args.push_back(snapshotbase + "@" + timestring);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), args, bp::process_stdio{{/* in to default*/}, out, {/* err to default */}});
|
||||
|
||||
std::string output;
|
||||
|
||||
boost::system::error_code ec;
|
||||
asio::read(out, asio::dynamic_buffer(output), ec);
|
||||
assert(!ec || (ec==asio::error::eof));
|
||||
proc.wait();
|
||||
|
||||
std::cout << output << std::endl;
|
||||
|
||||
ct++;
|
||||
}
|
||||
}
|
||||
|
||||
return ct;
|
||||
}
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after_one_day(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
{
|
||||
// after one day, we keep one backup per day
|
||||
|
||||
return handle_backups_after<1,30>(snapshotbase, times, ct, now);
|
||||
|
||||
/*if(ct == times.rend())
|
||||
return ct;
|
||||
|
||||
boost::posix_time::time_duration dur;
|
||||
boost::posix_time::ptime last_kept_time;
|
||||
|
||||
while( ct != times.rend() && (dur = now - *ct).hours() <= 30 * 24)
|
||||
{
|
||||
last_kept_time = *ct;
|
||||
std::cout << "Keeping Backup " << last_kept_time << " of this day." << std::endl;
|
||||
ct++;
|
||||
|
||||
while( ct != times.rend() && (dur = last_kept_time - *ct).hours() < 24)
|
||||
{
|
||||
std::cout << "Removing Backup " << *ct << " because we have already one in 24 hours." << std::endl;
|
||||
ct++;
|
||||
}
|
||||
}
|
||||
|
||||
return ct;*/
|
||||
}
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after_30_days(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
{
|
||||
// after 30 days, we keep one backup every 7 days
|
||||
|
||||
return handle_backups_after<7,365>(snapshotbase, times, ct, now);
|
||||
}
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator handle_backups_after_365_days(std::string & snapshotbase, std::set<boost::posix_time::ptime> & times, std::set<boost::posix_time::ptime>::reverse_iterator ct, boost::posix_time::ptime now)
|
||||
{
|
||||
// after 365 days, we keep one backup every 30 days
|
||||
|
||||
return handle_backups_after<30, 365*100>(snapshotbase, times, ct, now);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv){
|
||||
std::cout << "Hello, from zfsbackupcleaner!\n";
|
||||
|
||||
po::options_description options("Argumente");
|
||||
options.add_options()
|
||||
("help", "Hilfe anzeigen")
|
||||
("dry-run,n", "Test-Modus; keine Backups entfernen")
|
||||
("backupsystem", po::value<std::string>(), "Computer, dessen Backups bereinigt werden sollen")
|
||||
;
|
||||
|
||||
po::positional_options_description p;
|
||||
p.add("backupsystem", 1);
|
||||
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::store(po::command_line_parser(argc,argv).options(options).positional(p).run(), vm);
|
||||
po::notify(vm);
|
||||
} catch (const boost::program_options::invalid_command_line_syntax & error) {
|
||||
std::cout << "Error parsing commandline-arguments:" << std::endl;
|
||||
std::cout << error.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(vm.count("help") || !vm.count("backupsystem"))
|
||||
{
|
||||
std::cout << "Benutzung: zfsbackupcleaner [Optionen] <Backupsystem>" << std::endl << std::endl;
|
||||
std::cout << options << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(vm.count("dry-run"))
|
||||
dry_run = true;
|
||||
|
||||
std::string backupsystem = vm["backupsystem"].as<std::string>();
|
||||
|
||||
if(backupsystem != "workstation" && ! fs::exists("/backup/"+backupsystem))
|
||||
{
|
||||
std::cout << "Für das System >" << backupsystem << "< gibt es keine Backups." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
asio::io_context ctx;
|
||||
asio::readable_pipe out(ctx);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), {"list", "-t", "snapshot", "/backup/"+backupsystem}, bp::process_stdio{{/* in to default*/}, out, {/* err to default */}});
|
||||
|
||||
std::string output;
|
||||
|
||||
boost::system::error_code ec;
|
||||
asio::read(out, asio::dynamic_buffer(output), ec);
|
||||
assert(!ec || (ec==asio::error::eof));
|
||||
proc.wait();
|
||||
|
||||
//std::cout << "OUTPUT" << output << "END" << std::endl;
|
||||
|
||||
std::stringstream lines(output);
|
||||
|
||||
std::set<boost::posix_time::ptime> times;
|
||||
|
||||
std::string snapshotbase;
|
||||
|
||||
for(std::string line; std::getline(lines, line);)
|
||||
{
|
||||
std::string::size_type pos = line.find(' ');
|
||||
line = line.substr(0,pos);
|
||||
//std::cout << "X: " << line << std::endl;
|
||||
|
||||
if(line == "NAME")
|
||||
continue;
|
||||
|
||||
pos = line.find('@');
|
||||
snapshotbase = line.substr(0,pos);
|
||||
std::string timestring = line.substr(pos+1);
|
||||
timestring[10]=' ';
|
||||
timestring[13]=':';
|
||||
timestring[16]=':';
|
||||
boost::posix_time::ptime t(boost::posix_time::time_from_string(timestring));
|
||||
|
||||
times.insert(t);
|
||||
}
|
||||
|
||||
if(times.empty())
|
||||
{
|
||||
std::cout << "NO SNAPSHOTS FOUND — EXIT";
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::set<boost::posix_time::ptime>::reverse_iterator current_time = times.rbegin();
|
||||
|
||||
// handle fist 24 hours!!!
|
||||
|
||||
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
|
||||
|
||||
std::cout << "Gehe aus von aktueller Zeit: " << now << std::endl << std::endl;
|
||||
|
||||
boost::posix_time::time_duration dur;
|
||||
|
||||
while( (dur = now - *current_time).hours() <= 72)
|
||||
{
|
||||
std::cout << "Omitting Backup " << *current_time << " because it is too young to handle (" << dur.hours() << " hours old)." << std::endl;
|
||||
current_time++;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
current_time = handle_backups_after_one_day(snapshotbase, times, current_time, now);
|
||||
current_time = handle_backups_after_30_days(snapshotbase, times, current_time, now);
|
||||
current_time = handle_backups_after_365_days(snapshotbase, times, current_time, now);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue