mirror of
https://github.com/borgbackup/borg.git
synced 2024-12-25 01:06:50 +00:00
rspace: manage reserved space in repository
This commit is contained in:
parent
1cd2f4dca3
commit
b14c050f69
3 changed files with 120 additions and 1 deletions
|
@ -86,6 +86,7 @@ def get_func(args):
|
|||
from .rinfo_cmd import RInfoMixIn
|
||||
from .rdelete_cmd import RDeleteMixIn
|
||||
from .rlist_cmd import RListMixIn
|
||||
from .rspace_cmd import RSpaceMixIn
|
||||
from .serve_cmd import ServeMixIn
|
||||
from .tar_cmds import TarMixIn
|
||||
from .transfer_cmd import TransferMixIn
|
||||
|
@ -115,6 +116,7 @@ class Archiver(
|
|||
RDeleteMixIn,
|
||||
RInfoMixIn,
|
||||
RListMixIn,
|
||||
RSpaceMixIn,
|
||||
ServeMixIn,
|
||||
TarMixIn,
|
||||
TransferMixIn,
|
||||
|
@ -351,6 +353,7 @@ def build_parser(self):
|
|||
self.build_parser_rlist(subparsers, common_parser, mid_common_parser)
|
||||
self.build_parser_recreate(subparsers, common_parser, mid_common_parser)
|
||||
self.build_parser_rename(subparsers, common_parser, mid_common_parser)
|
||||
self.build_parser_rspace(subparsers, common_parser, mid_common_parser)
|
||||
self.build_parser_serve(subparsers, common_parser, mid_common_parser)
|
||||
self.build_parser_tar(subparsers, common_parser, mid_common_parser)
|
||||
self.build_parser_transfer(subparsers, common_parser, mid_common_parser)
|
||||
|
|
|
@ -48,8 +48,14 @@ def do_rcreate(self, args, repository, *, other_repository=None, other_manifest=
|
|||
" borg key export -r REPOSITORY encrypted-key-backup\n"
|
||||
" borg key export -r REPOSITORY --paper encrypted-key-backup.txt\n"
|
||||
" borg key export -r REPOSITORY --qr-html encrypted-key-backup.html\n"
|
||||
"2. Write down the borg key passphrase and store it at safe place.\n"
|
||||
"2. Write down the borg key passphrase and store it at safe place."
|
||||
)
|
||||
logger.warning(
|
||||
"\n"
|
||||
"Reserve some repository storage space now for emergencies like 'disk full'\n"
|
||||
"by running:\n"
|
||||
" borg rspace --reserve 1G"
|
||||
)
|
||||
|
||||
def build_parser_rcreate(self, subparsers, common_parser, mid_common_parser):
|
||||
from ._common import process_epilog
|
||||
|
|
110
src/borg/archiver/rspace_cmd.py
Normal file
110
src/borg/archiver/rspace_cmd.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
import argparse
|
||||
import math
|
||||
import os
|
||||
|
||||
from ._common import with_repository, Highlander
|
||||
from ..constants import * # NOQA
|
||||
from ..helpers import parse_file_size, format_file_size
|
||||
|
||||
from ..logger import create_logger
|
||||
|
||||
logger = create_logger()
|
||||
|
||||
|
||||
class RSpaceMixIn:
|
||||
@with_repository(lock=False, manifest=False)
|
||||
def do_rspace(self, args, repository):
|
||||
"""Manage reserved space in repository"""
|
||||
# we work without locking here because locks don't work with full disk.
|
||||
if args.reserve_space > 0:
|
||||
storage_space_reserve_object_size = 64 * 2**20 # 64 MiB per object
|
||||
count = math.ceil(float(args.reserve_space) / storage_space_reserve_object_size) # round up
|
||||
size = 0
|
||||
for i in range(count):
|
||||
data = os.urandom(storage_space_reserve_object_size) # counter-act fs compression/dedup
|
||||
repository.store_store(f"config/space-reserve.{i}", data)
|
||||
size += len(data)
|
||||
print(f"There is {format_file_size(size, iec=False)} reserved space in this repository now.")
|
||||
elif args.free_space:
|
||||
infos = repository.store_list("config")
|
||||
size = 0
|
||||
for info in infos:
|
||||
if info.name.startswith("space-reserve."):
|
||||
size += info.size
|
||||
repository.store_delete(f"config/{info.name}")
|
||||
print(f"Freed {format_file_size(size, iec=False)} in repository.")
|
||||
print("Now run borg prune or borg delete plus borg compact to free more space.")
|
||||
print("After that, do not forget to reserve space again for next time!")
|
||||
else: # print amount currently reserved
|
||||
infos = repository.store_list("config")
|
||||
size = 0
|
||||
for info in infos:
|
||||
if info.name.startswith("space-reserve."):
|
||||
size += info.size
|
||||
print(f"There is {format_file_size(size, iec=False)} reserved space in this repository.")
|
||||
print("In case you want to change the amount, use --free first to free all reserved space,")
|
||||
print("then use --reserve with the desired amount.")
|
||||
|
||||
def build_parser_rspace(self, subparsers, common_parser, mid_common_parser):
|
||||
from ._common import process_epilog
|
||||
|
||||
rspace_epilog = process_epilog(
|
||||
"""
|
||||
This command manages reserved space in a repository.
|
||||
|
||||
Borg can not work in disk-full conditions (can not lock a repo and thus can
|
||||
not run prune/delete or compact operations to free disk space).
|
||||
|
||||
To avoid running into dead-end situations like that, you can put some objects
|
||||
into a repository that take up some disk space. If you ever run into a
|
||||
disk-full situation, you can free that space and then borg will be able to
|
||||
run normally, so you can free more disk space by using prune/delete/compact.
|
||||
After that, don't forget to reserve space again, in case you run into that
|
||||
situation again at a later time.
|
||||
|
||||
Examples::
|
||||
|
||||
# Create a new repository:
|
||||
$ borg rcreate ...
|
||||
# Reserve approx. 1GB of space for emergencies:
|
||||
$ borg rspace --reserve 1G
|
||||
|
||||
# Check amount of reserved space in the repository:
|
||||
$ borg rspace
|
||||
|
||||
# EMERGENCY! Free all reserved space to get things back to normal:
|
||||
$ borg rspace --free
|
||||
$ borg prune ...
|
||||
$ borg delete ...
|
||||
$ borg compact -v # only this actually frees space of deleted archives
|
||||
$ borg rspace --reserve 1G # reserve space again for next time
|
||||
|
||||
|
||||
Reserved space is always rounded up to use full reservation blocks of 64MiB.
|
||||
"""
|
||||
)
|
||||
subparser = subparsers.add_parser(
|
||||
"rspace",
|
||||
parents=[common_parser],
|
||||
add_help=False,
|
||||
description=self.do_rspace.__doc__,
|
||||
epilog=rspace_epilog,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
help="manage reserved space in a repository",
|
||||
)
|
||||
subparser.set_defaults(func=self.do_rspace)
|
||||
subparser.add_argument(
|
||||
"--reserve",
|
||||
metavar="SPACE",
|
||||
dest="reserve_space",
|
||||
default=0,
|
||||
type=parse_file_size,
|
||||
action=Highlander,
|
||||
help="Amount of space to reserve (e.g. 100M, 1G). Default: 0.",
|
||||
)
|
||||
subparser.add_argument(
|
||||
"--free",
|
||||
dest="free_space",
|
||||
action="store_true",
|
||||
help="Free all reserved space. Don't forget to reserve space later again.",
|
||||
)
|
Loading…
Reference in a new issue