2
using TeeJee.FileSystem;
4
using TeeJee.JsonHelper;
5
using TeeJee.ProcessHelper;
6
using TeeJee.GtkHelper;
11
public class Snapshot : GLib.Object{
12
public string path = "";
13
public string name = "";
15
public string sys_uuid = "";
16
public string sys_distro = "";
17
public string app_version = "";
18
public string description = "";
19
public Gee.ArrayList<string> tags;
20
public Gee.ArrayList<string> exclude_list;
21
public Gee.ArrayList<FsTabEntry> fstab_list;
22
public bool is_valid = true;
25
private bool thr_success = false;
26
private bool thr_running = false;
27
//private int thr_retval = -1;
29
public Snapshot(string dir_path){
32
var f = File.new_for_path(dir_path);
33
var info = f.query_info("*", FileQueryInfoFlags.NONE);
36
name = info.get_name();
39
date = new DateTime.from_unix_utc(0);
40
tags = new Gee.ArrayList<string>();
41
exclude_list = new Gee.ArrayList<string>();
42
fstab_list = new Gee.ArrayList<FsTabEntry>();
49
log_error (e.message);
55
public string taglist{
58
foreach(string tag in tags){
65
foreach(string tag in value.split(" ")){
66
if (!tags.contains(tag.strip())){
67
tags.add(tag.strip());
73
public string taglist_short{
76
foreach(string tag in tags){
77
str += " " + tag.replace("ondemand","O").replace("boot","B").replace("hourly","H").replace("daily","D").replace("weekly","W").replace("monthly","M");
83
public void add_tag(string tag){
84
if (!tags.contains(tag.strip())){
85
tags.add(tag.strip());
86
update_control_file();
90
public void remove_tag(string tag){
91
if (tags.contains(tag.strip())){
92
tags.remove(tag.strip());
93
update_control_file();
97
public bool has_tag(string tag){
98
return tags.contains(tag.strip());
103
public void read_control_file(){
104
string ctl_file = path + "/info.json";
106
var f = File.new_for_path(ctl_file);
107
if (f.query_exists()) {
108
var parser = new Json.Parser();
110
parser.load_from_file(ctl_file);
112
log_error (e.message);
114
var node = parser.get_root();
115
var config = node.get_object();
118
if ((node == null)||(config == null)){
123
string val = json_get_string(config,"created","");
124
if (val.length > 0) {
125
DateTime date_utc = new DateTime.from_unix_utc(int64.parse(val));
126
date = date_utc.to_local();
129
sys_uuid = json_get_string(config,"sys-uuid","");
130
sys_distro = json_get_string(config,"sys-distro","");
131
taglist = json_get_string(config,"tags","");
132
description = json_get_string(config,"comments","");
133
app_version = json_get_string(config,"app-version","");
140
public void read_exclude_list(){
141
string list_file = path + "/exclude.list";
143
exclude_list.clear();
145
var f = File.new_for_path(list_file);
146
if (f.query_exists()) {
147
foreach(string path in file_read(list_file).split("\n")){
149
if (!exclude_list.contains(path) && path.length > 0){
150
exclude_list.add(path);
159
public void read_fstab_file(){
160
string fstab_path = path + "/localhost/etc/fstab";
161
fstab_list = FsTabEntry.read_fstab_file(fstab_path);
164
public void update_control_file(){
165
/* Updates tag and comments */
168
string ctl_file = path + "/info.json";
169
var f = File.new_for_path(ctl_file);
171
if (f.query_exists()) {
173
var parser = new Json.Parser();
175
parser.load_from_file(ctl_file);
177
log_error (e.message);
179
var node = parser.get_root();
180
var config = node.get_object();
182
config.set_string_member("tags", taglist);
183
config.set_string_member("comments", description);
185
var json = new Json.Generator();
188
node.set_object(config);
191
json.to_file(ctl_file);
194
log_error (e.message);
198
public void remove_control_file(){
199
string ctl_file = path + "/info.json";
200
file_delete(ctl_file);
203
public static Snapshot write_control_file(
204
string snapshot_path, DateTime dt_created,
205
string tag, string root_uuid, string distro_full_name){
207
var ctl_path = snapshot_path + "/info.json";
208
var config = new Json.Object();
210
config.set_string_member("created", dt_created.to_utc().to_unix().to_string());
211
config.set_string_member("sys-uuid", root_uuid);
212
config.set_string_member("sys-distro", distro_full_name);
213
config.set_string_member("app-version", AppVersion);
214
config.set_string_member("tags", tag);
215
config.set_string_member("comments", "");
217
var json = new Json.Generator();
220
var node = new Json.Node(NodeType.OBJECT);
221
node.set_object(config);
225
var f = File.new_for_path(ctl_path);
226
if (f.query_exists()){
230
json.to_file(ctl_path);
232
log_error (e.message);
235
return (new Snapshot(snapshot_path));
240
public bool has_subvolumes(){
241
foreach(FsTabEntry en in fstab_list){
242
if (en.options.contains("subvol=@")){
251
public bool remove(){
255
Thread.create<void> (remove_snapshot_thread, true);
256
} catch (ThreadError e) {
259
log_error (e.message);
264
Thread.usleep((ulong) GLib.TimeSpan.MILLISECOND * 500);
270
private void remove_snapshot_thread(){
276
log_msg(_("Removing snapshot") + " '%s'...".printf(name));
279
var f = File.new_for_path(path);
280
if(f.query_exists()){
281
cmd = "rm -rf \"%s\"".printf(path);
283
if (LOG_COMMANDS) { log_debug(cmd); }
285
Process.spawn_command_line_sync(cmd, out std_out, out std_err, out ret_val);
288
log_error(_("Failed to remove") + ": '%s'".printf(path));
294
log_msg(_("Removed") + ": '%s'".printf(path));
301
log_error(_("Directory not found") + ": '%s'".printf(path));
307
log_error (e.message);