First version for testing
parent
ea236a99e7
commit
98c4432d9c
|
|
@ -63,3 +63,4 @@ _deps
|
|||
*.kdev4
|
||||
.kdev4/
|
||||
|
||||
out/
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
cmake_minimum_required(VERSION 3.10.0)
|
||||
project(zfsbackupcleaner VERSION 0.1.0 LANGUAGES C CXX)
|
||||
|
||||
find_package(Boost COMPONENTS filesystem system date_time program_options process REQUIRED)
|
||||
|
||||
add_executable(zfsbackupcleaner main.cpp)
|
||||
target_link_libraries(zfsbackupcleaner boost_process boost_filesystem)
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": 8,
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "Clang 20.1.8 x86_64-pc-linux-gnu",
|
||||
"displayName": "Clang 20.1.8 x86_64-pc-linux-gnu",
|
||||
"description": "Compiler werden verwendet: C = /usr/bin/clang, CXX = /usr/bin/clang++",
|
||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
|
||||
"CMAKE_C_COMPILER": "/usr/bin/clang",
|
||||
"CMAKE_CXX_COMPILER": "/usr/bin/clang++",
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,183 @@
|
|||
#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 <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>
|
||||
|
||||
namespace bp = boost::process;
|
||||
namespace asio = boost::asio;
|
||||
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), {"destroy", "-v", "-n", snapshotbase + "@" + timestring}, 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, char**){
|
||||
std::cout << "Hello, from zfsbackupcleaner!\n";
|
||||
|
||||
asio::io_context ctx;
|
||||
asio::readable_pipe out(ctx);
|
||||
|
||||
bp::process proc(ctx, bp::environment::find_executable("zfs"), {"list", "-t snaphot", "/backup/workstation"}, 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 << "NOW " << now << 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++;
|
||||
}
|
||||
|
||||
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,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
full_name=$(readlink -f $0)
|
||||
dir_name=$(dirname $full_name)
|
||||
|
||||
#echo $dir_name
|
||||
|
||||
if [ "$1" == "list" ]; then
|
||||
cat $dir_name/data/list.txt
|
||||
fi
|
||||
|
||||
if [ "$1" == "destroy" ]; then
|
||||
echo $@
|
||||
fi
|
||||
Loading…
Reference in New Issue