1 /**
2 Copyright: Copyright (c) 2019, Joakim Brännström. All rights reserved.
3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 */
6 module dsnapshot.cmdgroup.diskusage;
7 
8 import logger = std.experimental.logger;
9 import std.array : empty;
10 import std.algorithm;
11 import std.exception : collectException;
12 
13 import dsnapshot.config : Config;
14 import dsnapshot.exception;
15 import dsnapshot.types;
16 
17 int cmdDiskUsage(Snapshot[] snapshots, const Config.Diskusage conf) nothrow {
18     import dsnapshot.layout;
19     import dsnapshot.layout_utils;
20 
21     if (conf.name.value.empty) {
22         logger.error("No snapshot name specified (-s|--snapshot)").collectException;
23         return 1;
24     }
25 
26     foreach (snapshot; snapshots.filter!(a => a.name == conf.name.value)) {
27         const cmdDu = snapshot.syncCmd.match!((None a) => null, (RsyncConfig a) => a.cmdDiskUsage);
28         if (cmdDu.empty) {
29             logger.errorf("cmd_du is not set for snapshot %s", snapshot.name).collectException;
30             return 1;
31         }
32 
33         try {
34             auto flow = snapshot.syncCmd.match!((None a) => None.init.Flow, (RsyncConfig a) => a
35                     .flow);
36             // dfmt off
37             return flow.match!((None a) => 1,
38                                (FlowRsyncToLocal a) => localDiskUsage(cmdDu, a.dst.value.Path),
39                                (FlowLocal a) => localDiskUsage(cmdDu, a.dst.value.Path),
40                                (FlowLocalToRsync a) => remoteDiskUsage(a.dst, snapshot.remoteCmd, cmdDu)
41                                );
42             // dfmt on
43         } catch (SnapshotException e) {
44             e.errMsg.match!(a => a.print).collectException;
45             logger.error(e.msg).collectException;
46         } catch (Exception e) {
47             logger.error(e.msg).collectException;
48             break;
49         }
50     }
51 
52     logger.errorf("No snapshot with the name %s found", conf.name.value).collectException;
53     logger.infof("Available snapshots are: %-(%s, %)",
54             snapshots.map!(a => a.name)).collectException;
55     return 1;
56 }
57 
58 int localDiskUsage(const string[] cmdDu, Path p) {
59     import std.process : spawnProcess, wait;
60 
61     auto cmd = cmdDu ~ p.toString;
62     logger.infof("%-(%s %)", cmd);
63     return spawnProcess(cmd).wait;
64 }
65 
66 int remoteDiskUsage(RsyncAddr addr, RemoteCmd remote, const string[] cmdDu) {
67     import std.process : spawnProcess, wait;
68 
69     auto cmd = remote.match!((SshRemoteCmd a) => a.rsh);
70     cmd ~= addr.addr ~ cmdDu ~ addr.path;
71     logger.infof("%-(%s %)", cmd);
72     return spawnProcess(cmd).wait;
73 }