frontends.rst 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. .. include:: ../global.rst.inc
  2. .. highlight:: json
  3. .. _json_output:
  4. All about JSON: How to develop frontends
  5. ========================================
  6. Borg does not have a public API on the Python level. That does not keep you from writing :code:`import borg`,
  7. but does mean that there are no release-to-release guarantees on what you might find in that package, not
  8. even for point releases (1.1.x), and there is no documentation beyond the code and the internals documents.
  9. Borg does on the other hand provide an API on a command-line level. In other words, a frontend should to
  10. (for example) create a backup archive just invoke :ref:`borg_create`.
  11. Logging
  12. -------
  13. Especially for graphical frontends it is important to be able to convey and reformat progress information
  14. in meaningful ways. The ``--log-json`` option turns the stderr stream of Borg into a stream of JSON lines,
  15. where each line is a JSON object. The *type* key of the object determines its other contents.
  16. Since JSON can only encode text, any string representing a file system path may miss non-text parts.
  17. The following types are in use. Progress information is governed by the usual rules for progress information,
  18. it is not produced unless ``--progress`` is specified.
  19. archive_progress
  20. Output during operations creating archives (:ref:`borg_create` and :ref:`borg_recreate`).
  21. The following keys exist, each represents the current progress.
  22. original_size
  23. Original size of data processed so far (before compression and deduplication)
  24. compressed_size
  25. Compressed size
  26. deduplicated_size
  27. Deduplicated size
  28. nfiles
  29. Number of (regular) files processed so far
  30. path
  31. Current path
  32. progress_message
  33. A message-based progress information with no concrete progress information, just a message
  34. saying what is currently worked on.
  35. operation
  36. unique, opaque integer ID of the operation
  37. :ref:`msgid <msgid>`
  38. Message ID of the operation (may be *none*)
  39. finished
  40. boolean indicating whether the operation has finished, only the last object for an *operation*
  41. can have this property set to *true*.
  42. message
  43. current progress message (may be empty/absent)
  44. progress_percent
  45. Absolute progress information with defined end/total and current value.
  46. operation
  47. unique, opaque integer ID of the operation
  48. :ref:`msgid <msgid>`
  49. Message ID of the operation (may be *none*)
  50. finished
  51. boolean indicating whether the operation has finished, only the last object for an *operation*
  52. can have this property set to *true*.
  53. message
  54. A formatted progress message, this will include the percentage and perhaps other information
  55. current
  56. Current value (always less-or-equal to *total*)
  57. info
  58. Array that describes the current item, may be *none*, contents depend on *msgid*
  59. total
  60. Total value
  61. file_status
  62. This is only output by :ref:`borg_create` and :ref:`borg_recreate` if ``--list`` is specified. The usual
  63. rules for the file listing applies, including the ``--filter`` option.
  64. status
  65. Single-character status as for regular list output
  66. path
  67. Path of the file system object
  68. log_message
  69. Any regular log output invokes this type. Regular log options and filtering applies to these as well.
  70. created
  71. Unix timestamp (float)
  72. levelname
  73. Upper-case log level name (also called severity). Defined levels are: DEBUG, INFO, WARNING, ERROR, CRITICAL
  74. name
  75. Name of the emitting entity
  76. message
  77. Formatted log message
  78. :ref:`msgid <msgid>`
  79. Message ID, may be *none* or absent
  80. .. rubric:: Examples (reformatted, each object would be on exactly one line)
  81. :ref:`borg_extract` progress::
  82. {"message": "100.0% Extracting: src/borgbackup.egg-info/entry_points.txt",
  83. "current": 13000228, "total": 13004993, "info": ["src/borgbackup.egg-info/entry_points.txt"],
  84. "operation": 1, "msgid": "extract", "type": "progress_percent", "finished": false}
  85. {"message": "100.0% Extracting: src/borgbackup.egg-info/SOURCES.txt",
  86. "current": 13004993, "total": 13004993, "info": ["src/borgbackup.egg-info/SOURCES.txt"],
  87. "operation": 1, "msgid": "extract", "type": "progress_percent", "finished": false}
  88. {"operation": 1, "msgid": "extract", "type": "progress_percent", "finished": true}
  89. :ref:`borg_create` file listing with progress::
  90. {"original_size": 0, "compressed_size": 0, "deduplicated_size": 0, "nfiles": 0, "type": "archive_progress", "path": "src"}
  91. {"type": "file_status", "status": "U", "path": "src/borgbackup.egg-info/entry_points.txt"}
  92. {"type": "file_status", "status": "U", "path": "src/borgbackup.egg-info/SOURCES.txt"}
  93. {"type": "file_status", "status": "d", "path": "src/borgbackup.egg-info"}
  94. {"type": "file_status", "status": "d", "path": "src"}
  95. {"original_size": 13176040, "compressed_size": 11386863, "deduplicated_size": 503, "nfiles": 277, "type": "archive_progress", "path": ""}
  96. Internal transaction progress::
  97. {"message": "Saving files cache", "operation": 2, "msgid": "cache.commit", "type": "progress_message", "finished": false}
  98. {"message": "Saving cache config", "operation": 2, "msgid": "cache.commit", "type": "progress_message", "finished": false}
  99. {"message": "Saving chunks cache", "operation": 2, "msgid": "cache.commit", "type": "progress_message", "finished": false}
  100. {"operation": 2, "msgid": "cache.commit", "type": "progress_message", "finished": true}
  101. A debug log message::
  102. {"message": "35 self tests completed in 0.08 seconds",
  103. "type": "log_message", "created": 1488278449.5575905, "levelname": "DEBUG", "name": "borg.archiver"}
  104. Standard output
  105. ---------------
  106. *stdout* is different and more command-dependent. Commands like :ref:`borg_info`, :ref:`borg_create`
  107. and :ref:`borg_list` implement a ``--json`` option which turns their regular output into a single JSON object.
  108. Dates are formatted according to ISO-8601 with the strftime format string '%a, %Y-%m-%d %H:%M:%S',
  109. e.g. *Sat, 2016-02-25 23:50:06*.
  110. The root object at least contains a *repository* key with an object containing:
  111. id
  112. The ID of the repository, normally 64 hex characters
  113. location
  114. Canonicalized repository path, thus this may be different from what is specified on the command line
  115. last_modified
  116. Date when the repository was last modified by the Borg client
  117. The *encryption* key, if present, contains:
  118. mode
  119. Textual encryption mode name (same as :ref:`borg_init` ``--encryption`` names)
  120. keyfile
  121. Path to the local key file used for access. Depending on *mode* this key may be absent.
  122. The *cache* key, if present, contains:
  123. path
  124. Path to the local repository cache
  125. stats
  126. Object containing cache stats:
  127. total_chunks
  128. Number of chunks
  129. total_unique_chunks
  130. Number of unique chunks
  131. total_size
  132. Total uncompressed size of all chunks multiplied with their reference counts
  133. total_csize
  134. Total compressed and encrypted size of all chunks multiplied with their reference counts
  135. unique_size
  136. Uncompressed size of all chunks
  137. unique_csize
  138. Compressed and encrypted size of all chunks
  139. Example *borg info* output::
  140. {
  141. "cache": {
  142. "path": "/home/user/.cache/borg/0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
  143. "stats": {
  144. "total_chunks": 511533,
  145. "total_csize": 17948017540,
  146. "total_size": 22635749792,
  147. "total_unique_chunks": 54892,
  148. "unique_csize": 1920405405,
  149. "unique_size": 2449675468
  150. }
  151. },
  152. "encryption": {
  153. "mode": "repokey"
  154. },
  155. "repository": {
  156. "id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
  157. "last_modified": "Mon, 2017-02-27 21:21:58",
  158. "location": "/home/user/testrepo"
  159. },
  160. "security_dir": "/home/user/.config/borg/security/0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23"
  161. }
  162. .. rubric:: Archive formats
  163. :ref:`borg_info` uses an extended format for archives, which is more expensive to retrieve, while
  164. :ref:`borg_list` uses a simpler format that is faster to retrieve. Either return archives in an
  165. array under the *archives* key, while :ref:`borg_create` returns a single archive object under the
  166. *archive* key.
  167. Both formats contain a *name* key with the archive name, the *id* key with the hexadecimal archive ID,
  168. and the *start* key with the start timestamp.
  169. info and create further have:
  170. end
  171. End timestamp
  172. duration
  173. Duration in seconds between start and end in seconds (float)
  174. stats
  175. Archive statistics (freshly calculated, this is what makes "info" more expensive)
  176. original_size
  177. Size of files and metadata before compression
  178. compressed_size
  179. Size after compression
  180. deduplicated_size
  181. Deduplicated size (against the current repository, not when the archive was created)
  182. nfiles
  183. Number of regular files in the archive
  184. limits
  185. Object describing the utilization of Borg limits
  186. max_archive_size
  187. Float between 0 and 1 describing how large this archive is relative to the maximum size allowed by Borg
  188. command_line
  189. Array of strings of the command line that created the archive
  190. The note about paths from above applies here as well.
  191. :ref:`borg_info` further has:
  192. hostname
  193. Hostname of the creating host
  194. username
  195. Name of the creating user
  196. comment
  197. Archive comment, if any
  198. Example of a simple archive listing (``borg list --last 1 --json``)::
  199. {
  200. "archives": [
  201. {
  202. "archive": "2017-02-27T21:21:51",
  203. "barchive": "2017-02-27T21:21:51",
  204. "id": "80cd07219ad725b3c5f665c1dcf119435c4dee1647a560ecac30f8d40221a46a",
  205. "name": "2017-02-27T21:21:51",
  206. "time": "Mon, 2017-02-27 21:21:52",
  207. "start": "Mon, 2017-02-27 21:21:52"
  208. }
  209. ],
  210. "encryption": {
  211. "mode": "repokey"
  212. },
  213. "repository": {
  214. "id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
  215. "last_modified": "Mon, 2017-02-27 21:21:58",
  216. "location": "/home/user/repository"
  217. }
  218. }
  219. The same archive with more information (``borg info --last 1 --json``)::
  220. {
  221. "archives": [
  222. {
  223. "command_line": [
  224. "/home/user/.local/bin/borg",
  225. "create",
  226. "/home/user/repository",
  227. "..."
  228. ],
  229. "comment": "",
  230. "duration": 5.641542,
  231. "end": "Mon, 2017-02-27 21:21:58",
  232. "hostname": "host",
  233. "id": "80cd07219ad725b3c5f665c1dcf119435c4dee1647a560ecac30f8d40221a46a",
  234. "limits": {
  235. "max_archive_size": 0.0001330855110409714
  236. },
  237. "name": "2017-02-27T21:21:51",
  238. "start": "Mon, 2017-02-27 21:21:52",
  239. "stats": {
  240. "compressed_size": 1880961894,
  241. "deduplicated_size": 2791,
  242. "nfiles": 53669,
  243. "original_size": 2400471280
  244. },
  245. "username": "user"
  246. }
  247. ],
  248. "cache": {
  249. "path": "/home/user/.cache/borg/0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
  250. "stats": {
  251. "total_chunks": 511533,
  252. "total_csize": 17948017540,
  253. "total_size": 22635749792,
  254. "total_unique_chunks": 54892,
  255. "unique_csize": 1920405405,
  256. "unique_size": 2449675468
  257. }
  258. },
  259. "encryption": {
  260. "mode": "repokey"
  261. },
  262. "repository": {
  263. "id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
  264. "last_modified": "Mon, 2017-02-27 21:21:58",
  265. "location": "/home/user/repository"
  266. }
  267. }
  268. .. rubric:: File listings
  269. Listing the contents of an archive can produce *a lot* of JSON. Each item (file, directory, ...) is described
  270. by one object in the *files* array of the :ref:`borg_list` output. Refer to the *borg list* documentation for
  271. the available keys and their meaning.
  272. Example (excerpt)::
  273. {
  274. "encryption": {
  275. "mode": "repokey"
  276. },
  277. "repository": {
  278. "id": "0cbe6166b46627fd26b97f8831e2ca97584280a46714ef84d2b668daf8271a23",
  279. "last_modified": "Mon, 2017-02-27 21:21:58",
  280. "location": "/home/user/repository"
  281. },
  282. "files": [
  283. {
  284. "type": "d",
  285. "mode": "drwxr-xr-x",
  286. "user": "user",
  287. "group": "user",
  288. "uid": 1000,
  289. "gid": 1000,
  290. "path": "linux",
  291. "healthy": true,
  292. "source": "",
  293. "linktarget": "",
  294. "flags": null,
  295. "isomtime": "Sat, 2016-05-07 19:46:01",
  296. "size": 0
  297. }
  298. ]
  299. }
  300. .. _msgid:
  301. Message IDs
  302. -----------
  303. Message IDs are strings that essentially give a log message or operation a name, without actually using the
  304. full text, since texts change more frequently. Message IDs are unambiguous and reduce the need to parse
  305. log messages.
  306. Assigned message IDs are:
  307. .. See scripts/errorlist.py; this is slightly edited.
  308. Errors
  309. Archive.AlreadyExists
  310. Archive {} already exists
  311. Archive.DoesNotExist
  312. Archive {} does not exist
  313. Archive.IncompatibleFilesystemEncodingError
  314. Failed to encode filename "{}" into file system encoding "{}". Consider configuring the LANG environment variable.
  315. Cache.CacheInitAbortedError
  316. Cache initialization aborted
  317. Cache.EncryptionMethodMismatch
  318. Repository encryption method changed since last access, refusing to continue
  319. Cache.RepositoryAccessAborted
  320. Repository access aborted
  321. Cache.RepositoryIDNotUnique
  322. Cache is newer than repository - do you have multiple, independently updated repos with same ID?
  323. Cache.RepositoryReplay
  324. Cache is newer than repository - this is either an attack or unsafe (multiple repos with same ID)
  325. Buffer.MemoryLimitExceeded
  326. Requested buffer size {} is above the limit of {}.
  327. ExtensionModuleError
  328. The Borg binary extension modules do not seem to be properly installed
  329. IntegrityError
  330. Data integrity error: {}
  331. NoManifestError
  332. Repository has no manifest.
  333. PlaceholderError
  334. Formatting Error: "{}".format({}): {}({})
  335. KeyfileInvalidError
  336. Invalid key file for repository {} found in {}.
  337. KeyfileMismatchError
  338. Mismatch between repository {} and key file {}.
  339. KeyfileNotFoundError
  340. No key file for repository {} found in {}.
  341. PassphraseWrong
  342. passphrase supplied in BORG_PASSPHRASE is incorrect
  343. PasswordRetriesExceeded
  344. exceeded the maximum password retries
  345. RepoKeyNotFoundError
  346. No key entry found in the config of repository {}.
  347. UnsupportedManifestError
  348. Unsupported manifest envelope. A newer version is required to access this repository.
  349. UnsupportedPayloadError
  350. Unsupported payload type {}. A newer version is required to access this repository.
  351. NotABorgKeyFile
  352. This file is not a borg key backup, aborting.
  353. RepoIdMismatch
  354. This key backup seems to be for a different backup repository, aborting.
  355. UnencryptedRepo
  356. Keymanagement not available for unencrypted repositories.
  357. UnknownKeyType
  358. Keytype {0} is unknown.
  359. LockError
  360. Failed to acquire the lock {}.
  361. LockErrorT
  362. Failed to acquire the lock {}.
  363. ConnectionClosed
  364. Connection closed by remote host
  365. InvalidRPCMethod
  366. RPC method {} is not valid
  367. PathNotAllowed
  368. Repository path not allowed
  369. RemoteRepository.RPCServerOutdated
  370. Borg server is too old for {}. Required version {}
  371. UnexpectedRPCDataFormatFromClient
  372. Borg {}: Got unexpected RPC data format from client.
  373. UnexpectedRPCDataFormatFromServer
  374. Got unexpected RPC data format from server:
  375. {}
  376. Repository.AlreadyExists
  377. Repository {} already exists.
  378. Repository.CheckNeeded
  379. Inconsistency detected. Please run "borg check {}".
  380. Repository.DoesNotExist
  381. Repository {} does not exist.
  382. Repository.InsufficientFreeSpaceError
  383. Insufficient free space to complete transaction (required: {}, available: {}).
  384. Repository.InvalidRepository
  385. {} is not a valid repository. Check repo config.
  386. Repository.ObjectNotFound
  387. Object with key {} not found in repository {}.
  388. Operations
  389. - cache.begin_transaction
  390. - cache.commit
  391. - cache.sync
  392. *info* is one string element, the name of the archive currently synced.
  393. - repository.compact_segments
  394. - repository.replay_segments
  395. - repository.check_segments
  396. - check.verify_data
  397. - extract
  398. *info* is one string element, the name of the path currently extracted.
  399. - extract.permissions
  400. - archive.delete