kind.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672
  1. # 1 "kind.ag"
  2. #include <dirent.h>
  3. # 2 "kind.ag"
  4. #include <sys/stat.h>
  5. # 3 "kind.ag"
  6. #include <cstring>
  7. # 4 "kind.ag"
  8. #include <unistd.h>
  9. # 5 "kind.ag"
  10. # 6 "kind.ag"
  11. #include <iostream>
  12. # 7 "kind.ag"
  13. #include <fstream>
  14. # 8 "kind.ag"
  15. # 9 "kind.ag"
  16. #include <string>
  17. # 10 "kind.ag"
  18. #include <vector>
  19. # 11 "kind.ag"
  20. #include <set>
  21. # 12 "kind.ag"
  22. # 13 "kind.ag"
  23. #include <algorithm>
  24. # 14 "kind.ag"
  25. # 15 "kind.ag"
  26. #include "stringtools.h"
  27. # 16 "kind.ag"
  28. #include "Exception.h"
  29. # 17 "kind.ag"
  30. # 18 "kind.ag"
  31. #include "DateTime.h"
  32. # 19 "kind.ag"
  33. #include "Strings.h"
  34. # 20 "kind.ag"
  35. #include "FileName.h"
  36. # 21 "kind.ag"
  37. #include "Image.h"
  38. # 22 "kind.ag"
  39. # 23 "kind.ag"
  40. #include "KindConfig.h"
  41. # 24 "kind.ag"
  42. #include "filetools.h"
  43. # 25 "kind.ag"
  44. #include "Lexer.h"
  45. # 26 "kind.ag"
  46. #include "rulecomp.h"
  47. # 27 "kind.ag"
  48. # 28 "kind.ag"
  49. #include "kind.h"
  50. # 29 "kind.ag"
  51. # 30 "kind.ag"
  52. #include "expiretools.h"
  53. # 31 "kind.ag"
  54. #include "excludetools.h"
  55. # 32 "kind.ag"
  56. # 33 "kind.ag"
  57. /*AppGen
  58. # 34 "kind.ag"
  59. %% Beschreibung des Programmes:
  60. # 35 "kind.ag"
  61. prog: archiving backup
  62. # 36 "kind.ag"
  63. %% Beschreibung Parameter
  64. # 37 "kind.ag"
  65. % symbolischerName, Art, Typ, Variablenname, Erklärung, Default-Wert
  66. # 38 "kind.ag"
  67. para: vault_or_group, required, string, vault, Vault to backup
  68. # 39 "kind.ag"
  69. %% Beschreibung der Optionen
  70. # 40 "kind.ag"
  71. % kurz-Option, lang-Option, Typ, Variablenname, Erklärung, Default-Wert
  72. # 41 "kind.ag"
  73. opt: c, masterconfig, string, masterConfig, Master config file, ""
  74. # 42 "kind.ag"
  75. opt2: if not given or empty kind looks for
  76. # 43 "kind.ag"
  77. opt2: /etc/kind/master.conf
  78. # 44 "kind.ag"
  79. opt2: /ffp/etc/kind/master.conf
  80. # 45 "kind.ag"
  81. opt: f, full, void, fullImage, Force full image == initial backup, false
  82. # 46 "kind.ag"
  83. opt: B, backup, void, doBackup, Backup, false
  84. # 47 "kind.ag"
  85. opt: E, expire, void, doExpire, Expire, false
  86. # 48 "kind.ag"
  87. opt: C, listconfig, void, listConfig, Show configuration, false
  88. # 49 "kind.ag"
  89. opt: I, listimages, void, listImages, List data of images, false
  90. # 50 "kind.ag"
  91. opt2: if none of backup, expire, listconfig and listimages is specified,
  92. # 51 "kind.ag"
  93. opt2: backup and expire is assumed.
  94. # 52 "kind.ag"
  95. opt2: listconfig and listimages cannot be combined with other actions
  96. # 53 "kind.ag"
  97. opt: D, dryrun, Void, dryRun, Dry run (no real backup), false
  98. # 54 "kind.ag"
  99. opt: F, forcebackup, string, forcedBackupSet, Create image for specified backup set, ""
  100. # 55 "kind.ag"
  101. opt: v, verbose, Void, verbose, Verbose, false
  102. # 56 "kind.ag"
  103. opt: d, debug, Void, debug, Debug output of many data, false
  104. # 57 "kind.ag"
  105. opt: q, quiet, Void, quiet, Be quiet - no messages, false
  106. # 58 "kind.ag"
  107. opt: h, help, usage, ignored , This help
  108. # 59 "kind.ag"
  109. AppGen*/
  110. # 60 "kind.ag"
  111. # 61 "kind.ag"
  112. using namespace std;
  113. # 62 "kind.ag"
  114. # 63 "kind.ag"
  115. /*AppGen:Global*/
  116. #include <getopt.h>
  117. #include <string>
  118. #include <string>
  119. #include <string>
  120. bool dryRun = false;
  121. bool verbose = false;
  122. bool debug = false;
  123. bool quiet = false;
  124. /*AppGen:GlobalEnd*/
  125. # 64 "kind.ag"
  126. # 65 "kind.ag"
  127. Strings banks;
  128. # 66 "kind.ag"
  129. # 67 "kind.ag"
  130. string findVault(const string& v);
  131. # 68 "kind.ag"
  132. # 69 "kind.ag"
  133. typedef pair<long int, long int> Sizes;
  134. # 70 "kind.ag"
  135. map<string, Sizes> sizes;
  136. # 71 "kind.ag"
  137. # 72 "kind.ag"
  138. void readSizes(const string& logSizeFile)
  139. # 73 "kind.ag"
  140. {
  141. # 74 "kind.ag"
  142. if (!logSizeFile.empty() && fileExists(logSizeFile))
  143. # 75 "kind.ag"
  144. {
  145. # 76 "kind.ag"
  146. vector<string> ss;
  147. # 77 "kind.ag"
  148. file2Strings(logSizeFile, ss);
  149. # 78 "kind.ag"
  150. for (const string& s : ss)
  151. # 79 "kind.ag"
  152. {
  153. # 80 "kind.ag"
  154. unsigned int i = 0;
  155. # 81 "kind.ag"
  156. string vault = getWord(s, i);
  157. # 82 "kind.ag"
  158. long int s1 = getLongInt(s, i);
  159. # 83 "kind.ag"
  160. long int s2 = getLongInt(s, i);
  161. # 84 "kind.ag"
  162. try
  163. # 85 "kind.ag"
  164. {
  165. # 86 "kind.ag"
  166. findVault(vault);
  167. # 87 "kind.ag"
  168. sizes[vault] = Sizes(s1, s2);
  169. # 88 "kind.ag"
  170. }
  171. # 89 "kind.ag"
  172. catch (...)
  173. # 90 "kind.ag"
  174. {
  175. # 91 "kind.ag"
  176. // ignore missing vaults
  177. # 92 "kind.ag"
  178. }
  179. # 93 "kind.ag"
  180. }
  181. # 94 "kind.ag"
  182. }
  183. # 95 "kind.ag"
  184. }
  185. # 96 "kind.ag"
  186. # 97 "kind.ag"
  187. void writeSizes(const string logSizeFile)
  188. # 98 "kind.ag"
  189. {
  190. # 99 "kind.ag"
  191. if (!logSizeFile.empty())
  192. # 100 "kind.ag"
  193. {
  194. # 101 "kind.ag"
  195. Strings st;
  196. # 102 "kind.ag"
  197. for (auto s : sizes)
  198. # 103 "kind.ag"
  199. {
  200. # 104 "kind.ag"
  201. string h = s.first + " " + to_string(s.second.first) + " " + to_string(s.second.second);
  202. # 105 "kind.ag"
  203. st.push_back(h);
  204. # 106 "kind.ag"
  205. }
  206. # 107 "kind.ag"
  207. strings2File(st, logSizeFile);
  208. # 108 "kind.ag"
  209. }
  210. # 109 "kind.ag"
  211. }
  212. # 110 "kind.ag"
  213. # 111 "kind.ag"
  214. void verbosePrint(const string& text)
  215. # 112 "kind.ag"
  216. {
  217. # 113 "kind.ag"
  218. if (verbose)
  219. # 114 "kind.ag"
  220. cout << " " << text << endl;
  221. # 115 "kind.ag"
  222. }
  223. # 116 "kind.ag"
  224. # 117 "kind.ag"
  225. void debugPrint(const string& text)
  226. # 118 "kind.ag"
  227. {
  228. # 119 "kind.ag"
  229. if (debug)
  230. # 120 "kind.ag"
  231. cout << " " << text << endl;
  232. # 121 "kind.ag"
  233. }
  234. # 122 "kind.ag"
  235. # 123 "kind.ag"
  236. void readMasterConfig1(const string& fn, KindConfig& conf)
  237. # 124 "kind.ag"
  238. {
  239. # 125 "kind.ag"
  240. verbosePrint("reading master config " + fn);
  241. # 126 "kind.ag"
  242. conf.addFile(fn);
  243. # 127 "kind.ag"
  244. }
  245. # 128 "kind.ag"
  246. # 129 "kind.ag"
  247. void readMasterConfig(const string& fn, KindConfig& conf)
  248. # 130 "kind.ag"
  249. {
  250. # 131 "kind.ag"
  251. if (!fn.empty()) // master config given by user on commandline
  252. # 132 "kind.ag"
  253. readMasterConfig1(fn, conf);
  254. # 133 "kind.ag"
  255. else if (fileExists("/etc/kind/master.conf"))
  256. # 134 "kind.ag"
  257. readMasterConfig1("/etc/kind/master.conf", conf);
  258. # 135 "kind.ag"
  259. else if (fileExists("/ffp/etc/kind/master.conf"))
  260. # 136 "kind.ag"
  261. readMasterConfig1("/ffp/etc/kind/master.conf", conf);
  262. # 137 "kind.ag"
  263. else
  264. # 138 "kind.ag"
  265. throw Exception("MasterConfig", "no file");
  266. # 139 "kind.ag"
  267. }
  268. # 140 "kind.ag"
  269. # 141 "kind.ag"
  270. string findVault(const string& v)
  271. # 142 "kind.ag"
  272. {
  273. # 143 "kind.ag"
  274. bool found = false;
  275. # 144 "kind.ag"
  276. FileName fn;
  277. # 145 "kind.ag"
  278. fn.setName(v);
  279. # 146 "kind.ag"
  280. for (unsigned int i = 0; !found && i < banks.size(); ++i)
  281. # 147 "kind.ag"
  282. {
  283. # 148 "kind.ag"
  284. fn.setPath(banks[i]);
  285. # 149 "kind.ag"
  286. if (dirExists(fn.getFileName()))
  287. # 150 "kind.ag"
  288. found = true;
  289. # 151 "kind.ag"
  290. }
  291. # 152 "kind.ag"
  292. if (!found)
  293. # 153 "kind.ag"
  294. throw Exception("find vault", v + " not found");
  295. # 154 "kind.ag"
  296. verbosePrint("using vault " + fn.getFileName());
  297. # 155 "kind.ag"
  298. return fn.getFileName();
  299. # 156 "kind.ag"
  300. }
  301. # 157 "kind.ag"
  302. # 158 "kind.ag"
  303. void readVaultConfig(const string& vault, KindConfig& conf)
  304. # 159 "kind.ag"
  305. {
  306. # 160 "kind.ag"
  307. string vaultpath = findVault(vault);
  308. # 161 "kind.ag"
  309. const string& vaultConfigName = vaultpath + '/' + conf.getString("vaultConfigName");
  310. # 162 "kind.ag"
  311. verbosePrint("reading vault config:");
  312. # 163 "kind.ag"
  313. verbosePrint(" " + vaultConfigName);
  314. # 164 "kind.ag"
  315. conf.addFile(vaultConfigName);
  316. # 165 "kind.ag"
  317. }
  318. # 166 "kind.ag"
  319. # 167 "kind.ag"
  320. string getImageName(const KindConfig& conf,
  321. # 168 "kind.ag"
  322. const string& vaultPath,
  323. # 169 "kind.ag"
  324. const DateTime& imageTime)
  325. # 170 "kind.ag"
  326. {
  327. # 171 "kind.ag"
  328. bool nonPortable = false;
  329. # 172 "kind.ag"
  330. string imageName = conf.getString("imageName");
  331. # 173 "kind.ag"
  332. for (unsigned int i = 0; !nonPortable && i < imageName.size(); ++i)
  333. # 174 "kind.ag"
  334. {
  335. # 175 "kind.ag"
  336. char c = imageName[i];
  337. # 176 "kind.ag"
  338. if (!isalnum(c) && c != '.' && c != '_')
  339. # 177 "kind.ag"
  340. nonPortable = true;
  341. # 178 "kind.ag"
  342. }
  343. # 179 "kind.ag"
  344. if (nonPortable)
  345. # 180 "kind.ag"
  346. throw Exception("getImageName", "Invalid character in image name " + imageName);
  347. # 181 "kind.ag"
  348. # 182 "kind.ag"
  349. if (!imageName.empty())
  350. # 183 "kind.ag"
  351. imageName += '-';
  352. # 184 "kind.ag"
  353. # 185 "kind.ag"
  354. string imageFullName = vaultPath + "/" + imageName ;
  355. # 186 "kind.ag"
  356. # 187 "kind.ag"
  357. if (conf.getBool("longImageName"))
  358. # 188 "kind.ag"
  359. imageFullName += imageTime.getString('m');
  360. # 189 "kind.ag"
  361. else
  362. # 190 "kind.ag"
  363. imageFullName += imageTime.getString('s');
  364. # 191 "kind.ag"
  365. # 192 "kind.ag"
  366. return imageFullName;
  367. # 193 "kind.ag"
  368. }
  369. # 194 "kind.ag"
  370. # 195 "kind.ag"
  371. Images findImages(const string& vaultpath, const KindConfig& conf, bool all)
  372. # 196 "kind.ag"
  373. {
  374. # 197 "kind.ag"
  375. Strings dirs;
  376. # 198 "kind.ag"
  377. debugPrint("searching images in " + vaultpath);
  378. # 199 "kind.ag"
  379. dirList(vaultpath, dirs);
  380. # 200 "kind.ag"
  381. # 201 "kind.ag"
  382. Images imageList;
  383. # 202 "kind.ag"
  384. for (string dir : dirs)
  385. # 203 "kind.ag"
  386. {
  387. # 204 "kind.ag"
  388. FileName fn(dir);
  389. # 205 "kind.ag"
  390. string imgname = conf.getString("imageName");
  391. # 206 "kind.ag"
  392. if (startsWith(fn.getName(), imgname))
  393. # 207 "kind.ag"
  394. {
  395. # 208 "kind.ag"
  396. debugPrint("Checking " + dir);
  397. # 209 "kind.ag"
  398. Image image(dir);
  399. # 210 "kind.ag"
  400. # 211 "kind.ag"
  401. if (all || image.valid)
  402. # 212 "kind.ag"
  403. imageList.push_back(image);
  404. # 213 "kind.ag"
  405. }
  406. # 214 "kind.ag"
  407. }
  408. # 215 "kind.ag"
  409. if (imageList.size() > 1)
  410. # 216 "kind.ag"
  411. sort(imageList.begin(), imageList.end());
  412. # 217 "kind.ag"
  413. return imageList;
  414. # 218 "kind.ag"
  415. }
  416. # 219 "kind.ag"
  417. # 220 "kind.ag"
  418. void listImageInfo(const string& vault,
  419. # 221 "kind.ag"
  420. KindConfig conf /*Copy!*/ ,
  421. # 222 "kind.ag"
  422. const DateTime& imageTime,
  423. # 223 "kind.ag"
  424. const string& backupSet)
  425. # 224 "kind.ag"
  426. {
  427. # 225 "kind.ag"
  428. readVaultConfig(vault, conf);
  429. # 226 "kind.ag"
  430. string vaultPath = findVault(vault);
  431. # 227 "kind.ag"
  432. Images imageList = findImages(vaultPath, conf, true);
  433. # 228 "kind.ag"
  434. cout << "== " << vault << " ==" << endl;
  435. # 229 "kind.ag"
  436. for (auto img : imageList)
  437. # 230 "kind.ag"
  438. {
  439. # 231 "kind.ag"
  440. if (img.series == backupSet || backupSet.empty())
  441. # 232 "kind.ag"
  442. {
  443. # 233 "kind.ag"
  444. img.printInfo();
  445. # 234 "kind.ag"
  446. cout << "---" << endl;
  447. # 235 "kind.ag"
  448. }
  449. # 236 "kind.ag"
  450. }
  451. # 237 "kind.ag"
  452. }
  453. # 238 "kind.ag"
  454. # 239 "kind.ag"
  455. void doBackup(const string& vault,
  456. # 240 "kind.ag"
  457. const string& imageFullName,
  458. # 241 "kind.ag"
  459. const string& referenceImage,
  460. # 242 "kind.ag"
  461. const KindConfig& conf)
  462. # 243 "kind.ag"
  463. {
  464. # 244 "kind.ag"
  465. // create image path
  466. # 245 "kind.ag"
  467. # 246 "kind.ag"
  468. bool shellMode = true;
  469. # 247 "kind.ag"
  470. # 248 "kind.ag"
  471. // create source descriptor
  472. # 249 "kind.ag"
  473. string host;
  474. # 250 "kind.ag"
  475. if (conf.hasKey("host"))
  476. # 251 "kind.ag"
  477. host = conf.getString("host");
  478. # 252 "kind.ag"
  479. # 253 "kind.ag"
  480. string server;
  481. # 254 "kind.ag"
  482. if (conf.hasKey("server"))
  483. # 255 "kind.ag"
  484. {
  485. # 256 "kind.ag"
  486. server = conf.getString("server");
  487. # 257 "kind.ag"
  488. shellMode = false;
  489. # 258 "kind.ag"
  490. }
  491. # 259 "kind.ag"
  492. # 260 "kind.ag"
  493. if (!host.empty() && !server.empty())
  494. # 261 "kind.ag"
  495. throw Exception("backupVault", "Cannot have host and server");
  496. # 262 "kind.ag"
  497. # 263 "kind.ag"
  498. if (host.empty() && server.empty())
  499. # 264 "kind.ag"
  500. throw Exception("backupVault", "No host or server specified");
  501. # 265 "kind.ag"
  502. # 266 "kind.ag"
  503. // ping host / server
  504. # 267 "kind.ag"
  505. // ping -c 1 -W 5 -q $HOST
  506. # 268 "kind.ag"
  507. string pingCommand = conf.getString("ping");
  508. # 269 "kind.ag"
  509. debugPrint("PingCommand: " + pingCommand);
  510. # 270 "kind.ag"
  511. if (!pingCommand.empty())
  512. # 271 "kind.ag"
  513. {
  514. # 272 "kind.ag"
  515. if (!host.empty())
  516. # 273 "kind.ag"
  517. replacePlaceHolder(pingCommand, "%host", host);
  518. # 274 "kind.ag"
  519. else
  520. # 275 "kind.ag"
  521. replacePlaceHolder(pingCommand, "%host", server);
  522. # 276 "kind.ag"
  523. int rc = 0;
  524. # 277 "kind.ag"
  525. Strings pingResult = localExec(pingCommand, rc, debug);
  526. # 278 "kind.ag"
  527. if (rc != 0)
  528. # 279 "kind.ag"
  529. throw Exception("Host not available", pingCommand);
  530. # 280 "kind.ag"
  531. }
  532. # 281 "kind.ag"
  533. # 282 "kind.ag"
  534. string path = conf.getString("path");
  535. # 283 "kind.ag"
  536. if (path.empty())
  537. # 284 "kind.ag"
  538. throw Exception("rsync", "empty source path");
  539. # 285 "kind.ag"
  540. if (path.back() != '/')
  541. # 286 "kind.ag"
  542. path += '/';
  543. # 287 "kind.ag"
  544. # 288 "kind.ag"
  545. string rsyncCmd = "rsync -vrltH --delete --stats -D --numeric-ids ";
  546. # 289 "kind.ag"
  547. if (!conf.getBool("ignorePermission"))
  548. # 290 "kind.ag"
  549. rsyncCmd += "-pgo";
  550. # 291 "kind.ag"
  551. vector<string> rso = conf.getStrings("rsyncOption");
  552. # 292 "kind.ag"
  553. for (const string& opt : rso)
  554. # 293 "kind.ag"
  555. rsyncCmd += opt + " ";
  556. # 294 "kind.ag"
  557. # 295 "kind.ag"
  558. // excludes
  559. # 296 "kind.ag"
  560. Strings excluded = getExclusions(conf, shellMode);
  561. # 297 "kind.ag"
  562. # 298 "kind.ag"
  563. // create image path
  564. # 299 "kind.ag"
  565. if (!dryRun)
  566. # 300 "kind.ag"
  567. if (mkdir(imageFullName.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)
  568. # 301 "kind.ag"
  569. throw Exception("Create image", "failed to create " + imageFullName);
  570. # 302 "kind.ag"
  571. # 303 "kind.ag"
  572. // error message
  573. # 304 "kind.ag"
  574. // we write an generic error message to mark backup as unsuccessful
  575. # 305 "kind.ag"
  576. // will be deleted at successful end of rsync
  577. # 306 "kind.ag"
  578. string errorfile = imageFullName + "/error";
  579. # 307 "kind.ag"
  580. if (!dryRun)
  581. # 308 "kind.ag"
  582. {
  583. # 309 "kind.ag"
  584. ofstream error(errorfile);
  585. # 310 "kind.ag"
  586. error << "failed" << endl;
  587. # 311 "kind.ag"
  588. error.close();
  589. # 312 "kind.ag"
  590. }
  591. # 313 "kind.ag"
  592. # 314 "kind.ag"
  593. if (shellMode) // shell mode
  594. # 315 "kind.ag"
  595. {
  596. # 316 "kind.ag"
  597. // cout << "USING SHELLMODE '" << host << "'" << endl;
  598. # 317 "kind.ag"
  599. string remoteShell = conf.getString("remoteShell");
  600. # 318 "kind.ag"
  601. string userAtHost = conf.getString("user") + "@" + conf.getString("host");
  602. # 319 "kind.ag"
  603. string rshCommand = remoteShell;
  604. # 320 "kind.ag"
  605. if (remoteShell.empty())
  606. # 321 "kind.ag"
  607. rshCommand = "ssh";
  608. # 322 "kind.ag"
  609. # 323 "kind.ag"
  610. rshCommand += " " + userAtHost;
  611. # 324 "kind.ag"
  612. # 325 "kind.ag"
  613. if (!dryRun)
  614. # 326 "kind.ag"
  615. strings2File(excluded, imageFullName + "/exclude");
  616. # 327 "kind.ag"
  617. # 328 "kind.ag"
  618. // rsync image
  619. # 329 "kind.ag"
  620. # 330 "kind.ag"
  621. if (!remoteShell.empty())
  622. # 331 "kind.ag"
  623. rsyncCmd += " -e \'" + remoteShell + "\' ";
  624. # 332 "kind.ag"
  625. # 333 "kind.ag"
  626. rsyncCmd += "--exclude-from=" + imageFullName + "/exclude ";
  627. # 334 "kind.ag"
  628. if (!referenceImage.empty())
  629. # 335 "kind.ag"
  630. rsyncCmd += "--link-dest=" + referenceImage + "/tree ";
  631. # 336 "kind.ag"
  632. rsyncCmd += userAtHost + ":" + path + " ";
  633. # 337 "kind.ag"
  634. rsyncCmd += imageFullName + "/tree";
  635. # 338 "kind.ag"
  636. } // shell mode
  637. # 339 "kind.ag"
  638. else
  639. # 340 "kind.ag"
  640. {
  641. # 341 "kind.ag"
  642. // cout << "USING SERVERMODE" << endl;
  643. # 342 "kind.ag"
  644. // we cannot use find without shell access
  645. # 343 "kind.ag"
  646. // and do not read an exclude file on client side
  647. # 344 "kind.ag"
  648. # 345 "kind.ag"
  649. if (!dryRun)
  650. # 346 "kind.ag"
  651. strings2File(excluded, imageFullName + "/exclude");
  652. # 347 "kind.ag"
  653. # 348 "kind.ag"
  654. rsyncCmd += "--exclude-from=" + imageFullName + "/exclude ";
  655. # 349 "kind.ag"
  656. if (!referenceImage.empty())
  657. # 350 "kind.ag"
  658. rsyncCmd += "--link-dest=" + referenceImage + "/tree ";
  659. # 351 "kind.ag"
  660. rsyncCmd += conf.getString("server") + "::" + path + " ";
  661. # 352 "kind.ag"
  662. rsyncCmd += imageFullName + "/tree";
  663. # 353 "kind.ag"
  664. }
  665. # 354 "kind.ag"
  666. # 355 "kind.ag"
  667. debugPrint("Action: " + rsyncCmd);
  668. # 356 "kind.ag"
  669. # 357 "kind.ag"
  670. vector<string> backupResult;
  671. # 358 "kind.ag"
  672. if (!dryRun)
  673. # 359 "kind.ag"
  674. {
  675. # 360 "kind.ag"
  676. verbosePrint("syncing (" + rsyncCmd + ")");
  677. # 361 "kind.ag"
  678. int rc;
  679. # 362 "kind.ag"
  680. backupResult = localExec(rsyncCmd, rc, debug, imageFullName + "/rsync-log");
  681. # 363 "kind.ag"
  682. if (rc == 0 ||
  683. # 364 "kind.ag"
  684. rc == 24 || // "no error" or "vanished source files" (ignored)
  685. # 365 "kind.ag"
  686. rc == 6144) // workaround for wrong exit code ??!!
  687. # 366 "kind.ag"
  688. {
  689. # 367 "kind.ag"
  690. unlink(errorfile.c_str());
  691. # 368 "kind.ag"
  692. long int st = 0;
  693. # 369 "kind.ag"
  694. long int sc = 0;
  695. # 370 "kind.ag"
  696. for (auto bl : backupResult)
  697. # 371 "kind.ag"
  698. {
  699. # 372 "kind.ag"
  700. if (startsWith(bl, "Total file size"))
  701. # 373 "kind.ag"
  702. st = getNumber(bl);
  703. # 374 "kind.ag"
  704. else if (startsWith(bl, "Total transferred file size"))
  705. # 375 "kind.ag"
  706. sc = getNumber(bl);
  707. # 376 "kind.ag"
  708. }
  709. # 377 "kind.ag"
  710. // sizes[vault] = pair<long int, long int>(st, sc);
  711. # 378 "kind.ag"
  712. sizes[vault] = Sizes(st, sc);
  713. # 379 "kind.ag"
  714. // cout << vault << " " << st << " || " << sc << endl;
  715. # 380 "kind.ag"
  716. }
  717. # 381 "kind.ag"
  718. else
  719. # 382 "kind.ag"
  720. throw Exception("Backup", "Failed to execute rsync (result: " + to_string(rc) + ")");
  721. # 383 "kind.ag"
  722. }
  723. # 384 "kind.ag"
  724. else
  725. # 385 "kind.ag"
  726. cout << "Not executing " << rsyncCmd << endl;
  727. # 386 "kind.ag"
  728. }
  729. # 387 "kind.ag"
  730. # 388 "kind.ag"
  731. bool backupVault(const string& vault,
  732. # 389 "kind.ag"
  733. KindConfig conf /*Copy!*/ ,
  734. # 390 "kind.ag"
  735. const DateTime& imageTime,
  736. # 391 "kind.ag"
  737. bool fullImage,
  738. # 392 "kind.ag"
  739. const string& forcedBackupSet)
  740. # 393 "kind.ag"
  741. {
  742. # 394 "kind.ag"
  743. if (!quiet)
  744. # 395 "kind.ag"
  745. cout << DateTime::now().getString('h') << ": Backup of vault " << vault << endl;
  746. # 396 "kind.ag"
  747. try
  748. # 397 "kind.ag"
  749. {
  750. # 398 "kind.ag"
  751. readVaultConfig(vault, conf);
  752. # 399 "kind.ag"
  753. # 400 "kind.ag"
  754. // where to store
  755. # 401 "kind.ag"
  756. string vaultPath = findVault(vault);
  757. # 402 "kind.ag"
  758. # 403 "kind.ag"
  759. // image path
  760. # 404 "kind.ag"
  761. string imageFullName = getImageName(conf, vaultPath, imageTime);
  762. # 405 "kind.ag"
  763. # 406 "kind.ag"
  764. bool backupNow = true;
  765. # 407 "kind.ag"
  766. # 408 "kind.ag"
  767. // existing images
  768. # 409 "kind.ag"
  769. Images validImageList = findImages(vaultPath, conf, false);
  770. # 410 "kind.ag"
  771. string currentSet = "expire"; // we are not using backupSets
  772. # 411 "kind.ag"
  773. # 412 "kind.ag"
  774. // check if we are using backup sets
  775. # 413 "kind.ag"
  776. # 414 "kind.ag"
  777. map<string, int> setIdx;
  778. # 415 "kind.ag"
  779. vector<SetRule> backupSetRule;
  780. # 416 "kind.ag"
  781. int setRuleIdx = -1;
  782. # 417 "kind.ag"
  783. # 418 "kind.ag"
  784. if (conf.hasKey("setRule"))
  785. # 419 "kind.ag"
  786. {
  787. # 420 "kind.ag"
  788. readSetRules(conf, setIdx, backupSetRule);
  789. # 421 "kind.ag"
  790. if (!setIdx.empty())
  791. # 422 "kind.ag"
  792. {
  793. # 423 "kind.ag"
  794. if (forcedBackupSet.empty())
  795. # 424 "kind.ag"
  796. {
  797. # 425 "kind.ag"
  798. backupNow = false;
  799. # 426 "kind.ag"
  800. # 427 "kind.ag"
  801. // find time for nextBackup for every backupSet
  802. # 428 "kind.ag"
  803. // defaults to now == imageTime;
  804. # 429 "kind.ag"
  805. vector<DateTime> nextBackup(backupSetRule.size(), imageTime);
  806. # 430 "kind.ag"
  807. # 431 "kind.ag"
  808. // find time for next backup
  809. # 432 "kind.ag"
  810. # 433 "kind.ag"
  811. for (const Image& image : validImageList)
  812. # 434 "kind.ag"
  813. {
  814. # 435 "kind.ag"
  815. if (image.series != "expire")
  816. # 436 "kind.ag"
  817. {
  818. # 437 "kind.ag"
  819. string s = image.series;
  820. # 438 "kind.ag"
  821. if (setIdx.count(s) > 0) // rule for set exists?
  822. # 439 "kind.ag"
  823. {
  824. # 440 "kind.ag"
  825. int rIdx = setIdx[s];
  826. # 441 "kind.ag"
  827. // image is valid for this and "lower level" backupSets
  828. # 442 "kind.ag"
  829. for (unsigned int i = rIdx; i < backupSetRule.size(); ++i)
  830. # 443 "kind.ag"
  831. if (nextBackup[i] < image.time + backupSetRule[i].distance)
  832. # 444 "kind.ag"
  833. nextBackup[i] = image.time + backupSetRule[i].distance;
  834. # 445 "kind.ag"
  835. }
  836. # 446 "kind.ag"
  837. }
  838. # 447 "kind.ag"
  839. }
  840. # 448 "kind.ag"
  841. if (debug)
  842. # 449 "kind.ag"
  843. for (unsigned int i = 0; i < backupSetRule.size(); ++i)
  844. # 450 "kind.ag"
  845. cout << " Next backup for " << backupSetRule[i].name << " at " << nextBackup[i].getString('h') << endl;
  846. # 451 "kind.ag"
  847. # 452 "kind.ag"
  848. // find backupSet that
  849. # 453 "kind.ag"
  850. // - needs backup
  851. # 454 "kind.ag"
  852. // - has longest time to keep
  853. # 455 "kind.ag"
  854. // because of ordered list backupSetRule this is the first set, that need
  855. # 456 "kind.ag"
  856. # 457 "kind.ag"
  857. currentSet = "";
  858. # 458 "kind.ag"
  859. for (unsigned int i = 0; i < backupSetRule.size() && currentSet.empty(); ++i)
  860. # 459 "kind.ag"
  861. {
  862. # 460 "kind.ag"
  863. string name = backupSetRule[i].name;
  864. # 461 "kind.ag"
  865. if (nextBackup[i] <= imageTime + 5) // small offset of 5s for "jitter"
  866. # 462 "kind.ag"
  867. {
  868. # 463 "kind.ag"
  869. backupNow = true;
  870. # 464 "kind.ag"
  871. currentSet = name;
  872. # 465 "kind.ag"
  873. setRuleIdx = i;
  874. # 466 "kind.ag"
  875. }
  876. # 467 "kind.ag"
  877. }
  878. # 468 "kind.ag"
  879. }
  880. # 469 "kind.ag"
  881. else
  882. # 470 "kind.ag"
  883. {
  884. # 471 "kind.ag"
  885. if (setIdx.count(forcedBackupSet) > 0)
  886. # 472 "kind.ag"
  887. {
  888. # 473 "kind.ag"
  889. currentSet = forcedBackupSet;
  890. # 474 "kind.ag"
  891. setRuleIdx = setIdx[forcedBackupSet];
  892. # 475 "kind.ag"
  893. }
  894. # 476 "kind.ag"
  895. else
  896. # 477 "kind.ag"
  897. throw Exception("force backup of set " + forcedBackupSet, " set not exists");
  898. # 478 "kind.ag"
  899. }
  900. # 479 "kind.ag"
  901. } // if (!setIdx.empty())
  902. # 480 "kind.ag"
  903. } // (conf.hasKey("setRule"))
  904. # 481 "kind.ag"
  905. # 482 "kind.ag"
  906. if (backupNow)
  907. # 483 "kind.ag"
  908. {
  909. # 484 "kind.ag"
  910. verbosePrint("backup to \"" + imageFullName + "\"");
  911. # 485 "kind.ag"
  912. if (setRuleIdx >= 0 && !quiet)
  913. # 486 "kind.ag"
  914. cout << " backup set is \"" << currentSet << "\"" << endl;
  915. # 487 "kind.ag"
  916. }
  917. # 488 "kind.ag"
  918. else if (!quiet)
  919. # 489 "kind.ag"
  920. cout << " no backup set needs update" << endl;
  921. # 490 "kind.ag"
  922. # 491 "kind.ag"
  923. if (backupNow)
  924. # 492 "kind.ag"
  925. {
  926. # 493 "kind.ag"
  927. // find reference image
  928. # 494 "kind.ag"
  929. string referenceImage;
  930. # 495 "kind.ag"
  931. if (!fullImage)
  932. # 496 "kind.ag"
  933. {
  934. # 497 "kind.ag"
  935. if (validImageList.empty())
  936. # 498 "kind.ag"
  937. throw Exception("backupVault", "no reference image found");
  938. # 499 "kind.ag"
  939. // last image is newest image
  940. # 500 "kind.ag"
  941. referenceImage = validImageList.back().name;
  942. # 501 "kind.ag"
  943. }
  944. # 502 "kind.ag"
  945. # 503 "kind.ag"
  946. doBackup(vault, imageFullName, referenceImage, conf);
  947. # 504 "kind.ag"
  948. # 505 "kind.ag"
  949. if (!dryRun)
  950. # 506 "kind.ag"
  951. {
  952. # 507 "kind.ag"
  953. string lastPath = vaultPath + "/last";
  954. # 508 "kind.ag"
  955. struct stat fstat;
  956. # 509 "kind.ag"
  957. # 510 "kind.ag"
  958. // remove last (dir or symlink)
  959. # 511 "kind.ag"
  960. if (lstat(lastPath.c_str(), &fstat) == 0) // last exists
  961. # 512 "kind.ag"
  962. {
  963. # 513 "kind.ag"
  964. if (S_ISDIR(fstat.st_mode))
  965. # 514 "kind.ag"
  966. removeDir(lastPath);
  967. # 515 "kind.ag"
  968. else
  969. # 516 "kind.ag"
  970. unlink(lastPath.c_str());
  971. # 517 "kind.ag"
  972. }
  973. # 518 "kind.ag"
  974. # 519 "kind.ag"
  975. string linkType = conf.getString("lastLink");
  976. # 520 "kind.ag"
  977. if (linkType == "hardLink")
  978. # 521 "kind.ag"
  979. {
  980. # 522 "kind.ag"
  981. int rc;
  982. # 523 "kind.ag"
  983. string hardLinkCommand = "cp -al " + imageFullName + " " + lastPath;
  984. # 524 "kind.ag"
  985. Strings res = localExec(hardLinkCommand, rc, debug);
  986. # 525 "kind.ag"
  987. }
  988. # 526 "kind.ag"
  989. else if (linkType == "symLink")
  990. # 527 "kind.ag"
  991. {
  992. # 528 "kind.ag"
  993. // set symlink to last image
  994. # 529 "kind.ag"
  995. symlink(imageFullName.c_str(), lastPath.c_str());
  996. # 530 "kind.ag"
  997. }
  998. # 531 "kind.ag"
  999. else if (linkType != "null")
  1000. # 532 "kind.ag"
  1001. cerr << "invalid Value in \"lastLink\"" << endl;
  1002. # 533 "kind.ag"
  1003. # 534 "kind.ag"
  1004. // write expire date to file
  1005. # 535 "kind.ag"
  1006. DateTime expireTime;
  1007. # 536 "kind.ag"
  1008. string rule;
  1009. # 537 "kind.ag"
  1010. if (setRuleIdx < 0) // not backup set based
  1011. # 538 "kind.ag"
  1012. expireTime = getExpireDate(imageTime, conf, rule);
  1013. # 539 "kind.ag"
  1014. else
  1015. # 540 "kind.ag"
  1016. {
  1017. # 541 "kind.ag"
  1018. expireTime = imageTime + backupSetRule[setRuleIdx].keep;
  1019. # 542 "kind.ag"
  1020. rule = backupSetRule[setRuleIdx].rule;
  1021. # 543 "kind.ag"
  1022. }
  1023. # 544 "kind.ag"
  1024. # 545 "kind.ag"
  1025. ofstream expireFile(imageFullName + "/expires");
  1026. # 546 "kind.ag"
  1027. expireFile << currentSet << "-" << expireTime.getString('m') << endl;
  1028. # 547 "kind.ag"
  1029. expireFile << rule << endl;
  1030. # 548 "kind.ag"
  1031. }
  1032. # 549 "kind.ag"
  1033. }
  1034. # 550 "kind.ag"
  1035. return backupNow;
  1036. # 551 "kind.ag"
  1037. }
  1038. # 552 "kind.ag"
  1039. catch (Exception ex)
  1040. # 553 "kind.ag"
  1041. {
  1042. # 554 "kind.ag"
  1043. cerr << "Exception in vault " << vault << ": " << ex.what() << endl;
  1044. # 555 "kind.ag"
  1045. return false;
  1046. # 556 "kind.ag"
  1047. }
  1048. # 557 "kind.ag"
  1049. }
  1050. # 558 "kind.ag"
  1051. # 559 "kind.ag"
  1052. void expireVault(const string& vault, KindConfig conf, DateTime now)
  1053. # 560 "kind.ag"
  1054. {
  1055. # 561 "kind.ag"
  1056. if (!quiet)
  1057. # 562 "kind.ag"
  1058. cout << DateTime::now().getString('h') << ": Expiring images in vault " << vault << endl;
  1059. # 563 "kind.ag"
  1060. # 564 "kind.ag"
  1061. readVaultConfig(vault, conf);
  1062. # 565 "kind.ag"
  1063. # 566 "kind.ag"
  1064. string vaultpath = findVault(vault);
  1065. # 567 "kind.ag"
  1066. # 568 "kind.ag"
  1067. Images imagelist = findImages(vaultpath, conf, true);
  1068. # 569 "kind.ag"
  1069. # 570 "kind.ag"
  1070. string lastValidImage;
  1071. # 571 "kind.ag"
  1072. for (Image image : imagelist)
  1073. # 572 "kind.ag"
  1074. {
  1075. # 573 "kind.ag"
  1076. if (image.valid)
  1077. # 574 "kind.ag"
  1078. lastValidImage = image.name;
  1079. # 575 "kind.ag"
  1080. }
  1081. # 576 "kind.ag"
  1082. # 577 "kind.ag"
  1083. for (Image image : imagelist)
  1084. # 578 "kind.ag"
  1085. {
  1086. # 579 "kind.ag"
  1087. if (debug)
  1088. # 580 "kind.ag"
  1089. image.printInfo();
  1090. # 581 "kind.ag"
  1091. # 582 "kind.ag"
  1092. DateTime imageTime = image.time;
  1093. # 583 "kind.ag"
  1094. # 584 "kind.ag"
  1095. if (imageTime != now && // ignore just created image
  1096. # 585 "kind.ag"
  1097. image.name != lastValidImage // ignore last valid image
  1098. # 586 "kind.ag"
  1099. )
  1100. # 587 "kind.ag"
  1101. {
  1102. # 588 "kind.ag"
  1103. DateTime expireTime;
  1104. # 589 "kind.ag"
  1105. string expireRule;
  1106. # 590 "kind.ag"
  1107. if (!image.valid) // invalid image?
  1108. # 591 "kind.ag"
  1109. {
  1110. # 592 "kind.ag"
  1111. time_t expPeriod = stot(conf.getString("expireFailedImage"));
  1112. # 593 "kind.ag"
  1113. if (expPeriod < 0)
  1114. # 594 "kind.ag"
  1115. throw Exception("expireFailedImage", "Time period must be positive");
  1116. # 595 "kind.ag"
  1117. expireTime = imageTime + stot(conf.getString("expireFailedImage"));
  1118. # 596 "kind.ag"
  1119. expireRule = "invalid image: " + conf.getString("expireFailedImage");
  1120. # 597 "kind.ag"
  1121. debugPrint("- invalid image");
  1122. # 598 "kind.ag"
  1123. }
  1124. # 599 "kind.ag"
  1125. else
  1126. # 600 "kind.ag"
  1127. {
  1128. # 601 "kind.ag"
  1129. debugPrint("- valid image");
  1130. # 602 "kind.ag"
  1131. expireTime = image.expire;
  1132. # 603 "kind.ag"
  1133. expireRule = image.expireRule;
  1134. # 604 "kind.ag"
  1135. }
  1136. # 605 "kind.ag"
  1137. # 606 "kind.ag"
  1138. if (expireTime < now)
  1139. # 607 "kind.ag"
  1140. {
  1141. # 608 "kind.ag"
  1142. if (!quiet)
  1143. # 609 "kind.ag"
  1144. cout << " removing image " << image.name << endl;
  1145. # 610 "kind.ag"
  1146. try
  1147. # 611 "kind.ag"
  1148. {
  1149. # 612 "kind.ag"
  1150. if (removeDir(image.name) != 0)
  1151. # 613 "kind.ag"
  1152. cout << "Error removing " << image.name << endl;
  1153. # 614 "kind.ag"
  1154. }
  1155. # 615 "kind.ag"
  1156. catch (Exception ex)
  1157. # 616 "kind.ag"
  1158. {
  1159. # 617 "kind.ag"
  1160. cerr << "Exception: " << ex.what() << endl;
  1161. # 618 "kind.ag"
  1162. }
  1163. # 619 "kind.ag"
  1164. }
  1165. # 620 "kind.ag"
  1166. }
  1167. # 621 "kind.ag"
  1168. else
  1169. # 622 "kind.ag"
  1170. debugPrint("- current image - ignored");
  1171. # 623 "kind.ag"
  1172. }
  1173. # 624 "kind.ag"
  1174. }
  1175. # 625 "kind.ag"
  1176. # 626 "kind.ag"
  1177. /*AppGen:Main*/
  1178. string ag_programName;
  1179. void usage()
  1180. {
  1181. cout << ag_programName << " - archiving backup" << endl;
  1182. cout << "Usage:" << endl;
  1183. cout << ag_programName << " [<options>] vault_or_group " << endl;
  1184. cout << " vault_or_group - Vault to backup" << endl;
  1185. cout << "Options:" << endl;
  1186. cout << " -c <s> --masterconfig=<s>" << endl;
  1187. cout << " Master config file (default: \"\")" << endl;
  1188. cout << " if not given or empty kind looks for" << endl;
  1189. cout << " /etc/kind/master.conf" << endl;
  1190. cout << " /ffp/etc/kind/master.conf" << endl;
  1191. cout << " -f --full" << endl;
  1192. cout << " Force full image == initial backup (default: false)" << endl;
  1193. cout << " -B --backup" << endl;
  1194. cout << " Backup (default: false)" << endl;
  1195. cout << " -E --expire" << endl;
  1196. cout << " Expire (default: false)" << endl;
  1197. cout << " -C --listconfig" << endl;
  1198. cout << " Show configuration (default: false)" << endl;
  1199. cout << " -I --listimages" << endl;
  1200. cout << " List data of images (default: false)" << endl;
  1201. cout << " if none of backup, expire, listconfig and listimages is specified," << endl;
  1202. cout << " backup and expire is assumed." << endl;
  1203. cout << " listconfig and listimages cannot be combined with other actions" << endl;
  1204. cout << " -D --dryrun" << endl;
  1205. cout << " Dry run (no real backup) (default: false)" << endl;
  1206. cout << " -F <s> --forcebackup=<s>" << endl;
  1207. cout << " Create image for specified backup set (default: \"\")" << endl;
  1208. cout << " -v --verbose" << endl;
  1209. cout << " Verbose (default: false)" << endl;
  1210. cout << " -d --debug" << endl;
  1211. cout << " Debug output of many data (default: false)" << endl;
  1212. cout << " -q --quiet" << endl;
  1213. cout << " Be quiet - no messages (default: false)" << endl;
  1214. cout << " -h --help" << endl;
  1215. cout << " This help" << endl;
  1216. exit(1);
  1217. }
  1218. void error(const string& msg)
  1219. {
  1220. cout << endl << ag_programName << " - error: " << msg << endl << endl;
  1221. usage();
  1222. }
  1223. int ptoi(const char* para)
  1224. {
  1225. char* end;
  1226. int res = strtol(para, &end, 10);
  1227. if (end == para)
  1228. error(string("no int: ") + para);
  1229. if (*end != 0)
  1230. error(string("garbage in int: ") + para);
  1231. return res;
  1232. }
  1233. double ptod(const char* para)
  1234. {
  1235. char* end;
  1236. double res = strtod(para, &end);
  1237. if (end == para)
  1238. error(string("no double: ") + para);
  1239. if (*end != 0)
  1240. error(string("garbage in double: ") + para);
  1241. return res;
  1242. }
  1243. int main(int argc, char** argv)
  1244. {
  1245. string masterConfig = "";
  1246. bool fullImage = false;
  1247. bool doBackup = false;
  1248. bool doExpire = false;
  1249. bool listConfig = false;
  1250. bool listImages = false;
  1251. string forcedBackupSet = "";
  1252. string vault = "";
  1253. static struct option ag_long_options[] =
  1254. {
  1255. {"masterconfig", required_argument, 0, 'c' },
  1256. {"full", no_argument, 0, 'f' },
  1257. {"backup", no_argument, 0, 'B' },
  1258. {"expire", no_argument, 0, 'E' },
  1259. {"listconfig", no_argument, 0, 'C' },
  1260. {"listimages", no_argument, 0, 'I' },
  1261. {"dryrun", no_argument, 0, 'D' },
  1262. {"forcebackup", required_argument, 0, 'F' },
  1263. {"verbose", no_argument, 0, 'v' },
  1264. {"debug", no_argument, 0, 'd' },
  1265. {"quiet", no_argument, 0, 'q' },
  1266. {"help", no_argument, 0, 'h' },
  1267. {0, 0, 0, 0 }
  1268. };
  1269. ag_programName = argv[0];
  1270. int rc;
  1271. opterr = 0;
  1272. while ((rc = getopt_long(argc, argv, ":c:fBECIDF:vdqh", ag_long_options, NULL)) >= 0)
  1273. {
  1274. switch (rc)
  1275. {
  1276. case '?':
  1277. error("Unknown option");
  1278. break;
  1279. case ':':
  1280. error("Expecting option parameter");
  1281. break;
  1282. case 'c':
  1283. masterConfig = optarg;
  1284. break;
  1285. case 'f':
  1286. fullImage = true;
  1287. break;
  1288. case 'B':
  1289. doBackup = true;
  1290. break;
  1291. case 'E':
  1292. doExpire = true;
  1293. break;
  1294. case 'C':
  1295. listConfig = true;
  1296. break;
  1297. case 'I':
  1298. listImages = true;
  1299. break;
  1300. case 'D':
  1301. dryRun = true;
  1302. break;
  1303. case 'F':
  1304. forcedBackupSet = optarg;
  1305. break;
  1306. case 'v':
  1307. verbose = true;
  1308. break;
  1309. case 'd':
  1310. debug = true;
  1311. break;
  1312. case 'q':
  1313. quiet = true;
  1314. break;
  1315. case 'h':
  1316. usage();
  1317. break;
  1318. default:
  1319. error("error in options");
  1320. }
  1321. }
  1322. if (optind < argc)
  1323. vault = argv[optind++];
  1324. else error("Parameter vault_or_group needed");
  1325. /*AppGen:MainEnd*/
  1326. # 630 "kind.ag"
  1327. # 631 "kind.ag"
  1328. int exitCode = 0;
  1329. # 632 "kind.ag"
  1330. string lockFile;
  1331. # 633 "kind.ag"
  1332. try
  1333. # 634 "kind.ag"
  1334. {
  1335. # 635 "kind.ag"
  1336. // handling of parameters and switches
  1337. # 636 "kind.ag"
  1338. if (debug) // debug implies verbose
  1339. # 637 "kind.ag"
  1340. verbose = true;
  1341. # 638 "kind.ag"
  1342. # 639 "kind.ag"
  1343. if (!doBackup && !doExpire && !listConfig && !listImages)
  1344. # 640 "kind.ag"
  1345. {
  1346. # 641 "kind.ag"
  1347. doBackup = true;
  1348. # 642 "kind.ag"
  1349. doExpire = true;
  1350. # 643 "kind.ag"
  1351. }
  1352. # 644 "kind.ag"
  1353. # 645 "kind.ag"
  1354. KindConfig conf;
  1355. # 646 "kind.ag"
  1356. # 647 "kind.ag"
  1357. // default-values
  1358. # 648 "kind.ag"
  1359. conf.add("imageName", "image");
  1360. # 649 "kind.ag"
  1361. conf.add("vaultConfigName", "kind/vault.conf");
  1362. # 650 "kind.ag"
  1363. conf.add("expireFailedImage", "3 days");
  1364. # 651 "kind.ag"
  1365. conf.add("expireRule", "* * * * 1 month");
  1366. # 652 "kind.ag"
  1367. conf.add("ping", "ping -c 1 -W 5 %host");
  1368. # 653 "kind.ag"
  1369. conf.add("rsyncOption", ""); // no additional rsync option
  1370. # 654 "kind.ag"
  1371. conf.add("remoteShell", "");
  1372. # 655 "kind.ag"
  1373. conf.add("lockfile", "/var/lock/kind");
  1374. # 656 "kind.ag"
  1375. conf.add("userExcludeFile", "nobackup.list");
  1376. # 657 "kind.ag"
  1377. conf.add("userExcludeCommand",
  1378. # 658 "kind.ag"
  1379. "find %path -type f -iname '*nobackup' -printf '%P\\\\n'");
  1380. # 659 "kind.ag"
  1381. conf.add("logSize", "");
  1382. # 660 "kind.ag"
  1383. conf.add("lastLink", "symLink");
  1384. # 661 "kind.ag"
  1385. # 662 "kind.ag"
  1386. if (listConfig)
  1387. # 663 "kind.ag"
  1388. {
  1389. # 664 "kind.ag"
  1390. cout << "builtin config" << endl;
  1391. # 665 "kind.ag"
  1392. conf.print(". ");
  1393. # 666 "kind.ag"
  1394. }
  1395. # 667 "kind.ag"
  1396. # 668 "kind.ag"
  1397. readMasterConfig(masterConfig, conf);
  1398. # 669 "kind.ag"
  1399. # 670 "kind.ag"
  1400. banks = conf.getStrings("bank");
  1401. # 671 "kind.ag"
  1402. if (banks.empty())
  1403. # 672 "kind.ag"
  1404. throw Exception("read master configuration", "no banks defined");
  1405. # 673 "kind.ag"
  1406. # 674 "kind.ag"
  1407. vector<string> vaults;
  1408. # 675 "kind.ag"
  1409. string groupname = "group_" + vault;
  1410. # 676 "kind.ag"
  1411. if (conf.hasKey(groupname))
  1412. # 677 "kind.ag"
  1413. {
  1414. # 678 "kind.ag"
  1415. vaults = conf.getStrings(groupname);
  1416. # 679 "kind.ag"
  1417. vault.clear(); // no single vault but group
  1418. # 680 "kind.ag"
  1419. }
  1420. # 681 "kind.ag"
  1421. else
  1422. # 682 "kind.ag"
  1423. vaults.push_back(vault);
  1424. # 683 "kind.ag"
  1425. # 684 "kind.ag"
  1426. if (listConfig)
  1427. # 685 "kind.ag"
  1428. {
  1429. # 686 "kind.ag"
  1430. cout << "global config:" << endl;
  1431. # 687 "kind.ag"
  1432. conf.print(". ");
  1433. # 688 "kind.ag"
  1434. if (!vault.empty())
  1435. # 689 "kind.ag"
  1436. {
  1437. # 690 "kind.ag"
  1438. readVaultConfig(vault, conf);
  1439. # 691 "kind.ag"
  1440. cout << "vault config:" << endl;
  1441. # 692 "kind.ag"
  1442. conf.print(". ");
  1443. # 693 "kind.ag"
  1444. }
  1445. # 694 "kind.ag"
  1446. else
  1447. # 695 "kind.ag"
  1448. cout << "specify single vault (not group) to see vault config" << endl;
  1449. # 696 "kind.ag"
  1450. exit(0);
  1451. # 697 "kind.ag"
  1452. }
  1453. # 698 "kind.ag"
  1454. # 699 "kind.ag"
  1455. DateTime imageTime = DateTime::now();
  1456. # 700 "kind.ag"
  1457. # 701 "kind.ag"
  1458. if (listImages)
  1459. # 702 "kind.ag"
  1460. {
  1461. # 703 "kind.ag"
  1462. for (string vault : vaults)
  1463. # 704 "kind.ag"
  1464. listImageInfo(vault, conf, imageTime, forcedBackupSet);
  1465. # 705 "kind.ag"
  1466. exit(0);
  1467. # 706 "kind.ag"
  1468. }
  1469. # 707 "kind.ag"
  1470. # 708 "kind.ag"
  1471. // previous actions do not need locking
  1472. # 709 "kind.ag"
  1473. lockFile = conf.getString("lockfile");
  1474. # 710 "kind.ag"
  1475. createLock(lockFile);
  1476. # 711 "kind.ag"
  1477. # 712 "kind.ag"
  1478. string logSizeFile = conf.getString("logSize");
  1479. # 713 "kind.ag"
  1480. readSizes(logSizeFile);
  1481. # 714 "kind.ag"
  1482. # 715 "kind.ag"
  1483. for (string vault : vaults)
  1484. # 716 "kind.ag"
  1485. {
  1486. # 717 "kind.ag"
  1487. if (doBackup)
  1488. # 718 "kind.ag"
  1489. if (backupVault(vault, conf, imageTime, fullImage, forcedBackupSet))
  1490. # 719 "kind.ag"
  1491. writeSizes(logSizeFile);
  1492. # 720 "kind.ag"
  1493. if (doExpire)
  1494. # 721 "kind.ag"
  1495. expireVault(vault, conf, imageTime);
  1496. # 722 "kind.ag"
  1497. }
  1498. # 723 "kind.ag"
  1499. # 724 "kind.ag"
  1500. if (!quiet)
  1501. # 725 "kind.ag"
  1502. cout << DateTime::now().getString('h') << ": finished" << endl;
  1503. # 726 "kind.ag"
  1504. # 727 "kind.ag"
  1505. }
  1506. # 728 "kind.ag"
  1507. catch (const Exception& ex)
  1508. # 729 "kind.ag"
  1509. {
  1510. # 730 "kind.ag"
  1511. cerr << "Exception: " << ex.what() << endl;
  1512. # 731 "kind.ag"
  1513. exitCode = 1;
  1514. # 732 "kind.ag"
  1515. }
  1516. # 733 "kind.ag"
  1517. catch (const char* msg)
  1518. # 734 "kind.ag"
  1519. {
  1520. # 735 "kind.ag"
  1521. cerr << "Exception(char*): " << msg << endl;
  1522. # 736 "kind.ag"
  1523. exitCode = 1;
  1524. # 737 "kind.ag"
  1525. }
  1526. # 738 "kind.ag"
  1527. catch (const string& msg)
  1528. # 739 "kind.ag"
  1529. {
  1530. # 740 "kind.ag"
  1531. cerr << "Exception(string): " << msg << endl;
  1532. # 741 "kind.ag"
  1533. exitCode = 1;
  1534. # 742 "kind.ag"
  1535. }
  1536. # 743 "kind.ag"
  1537. removeLock(lockFile);
  1538. # 744 "kind.ag"
  1539. return exitCode;
  1540. # 745 "kind.ag"
  1541. }