upgrader.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import logging
  2. logger = logging.getLogger(__name__)
  3. import os
  4. import shutil
  5. import tempfile
  6. import pytest
  7. try:
  8. import attic.repository
  9. import attic.key
  10. import attic.helpers
  11. except ImportError:
  12. attic = None
  13. from ..upgrader import AtticRepositoryUpgrader, AtticKeyfileKey
  14. from ..helpers import get_keys_dir
  15. from ..key import KeyfileKey
  16. from ..repository import Repository, MAGIC
  17. pytestmark = pytest.mark.skipif(attic is None,
  18. reason='cannot find an attic install')
  19. def repo_valid(path):
  20. """
  21. utility function to check if borg can open a repository
  22. :param path: the path to the repository
  23. :returns: if borg can check the repository
  24. """
  25. repository = Repository(str(path), create=False)
  26. # can't check raises() because check() handles the error
  27. state = repository.check()
  28. repository.close()
  29. return state
  30. def key_valid(path):
  31. """
  32. check that the new keyfile is alright
  33. :param path: the path to the key file
  34. :returns: if the file starts with the borg magic string
  35. """
  36. keyfile = os.path.join(get_keys_dir(),
  37. os.path.basename(path))
  38. with open(keyfile, 'r') as f:
  39. return f.read().startswith(KeyfileKey.FILE_ID)
  40. @pytest.fixture()
  41. def attic_repo(tmpdir):
  42. """
  43. create an attic repo with some stuff in it
  44. :param tmpdir: path to the repository to be created
  45. :returns: a attic.repository.Repository object
  46. """
  47. attic_repo = attic.repository.Repository(str(tmpdir), create=True)
  48. # throw some stuff in that repo, copied from `RepositoryTestCase.test1`
  49. for x in range(100):
  50. attic_repo.put(('%-32d' % x).encode('ascii'), b'SOMEDATA')
  51. attic_repo.commit()
  52. attic_repo.close()
  53. return attic_repo
  54. def test_convert_segments(tmpdir, attic_repo):
  55. """test segment conversion
  56. this will load the given attic repository, list all the segments
  57. then convert them one at a time. we need to close the repo before
  58. conversion otherwise we have errors from borg
  59. :param tmpdir: a temporary directory to run the test in (builtin
  60. fixture)
  61. :param attic_repo: a populated attic repository (fixture)
  62. """
  63. # check should fail because of magic number
  64. assert not repo_valid(tmpdir)
  65. logger.info("opening attic repository with borg and converting")
  66. repo = AtticRepositoryUpgrader(str(tmpdir), create=False)
  67. segments = [filename for i, filename in repo.io.segment_iterator()]
  68. repo.close()
  69. repo.convert_segments(segments, dryrun=False)
  70. repo.convert_cache(dryrun=False)
  71. assert repo_valid(tmpdir)
  72. class MockArgs:
  73. """
  74. mock attic location
  75. this is used to simulate a key location with a properly loaded
  76. repository object to create a key file
  77. """
  78. def __init__(self, path):
  79. self.repository = attic.helpers.Location(path)
  80. @pytest.fixture()
  81. def attic_key_file(attic_repo, tmpdir):
  82. """
  83. create an attic key file from the given repo, in the keys
  84. subdirectory of the given tmpdir
  85. :param attic_repo: an attic.repository.Repository object (fixture
  86. define above)
  87. :param tmpdir: a temporary directory (a builtin fixture)
  88. :returns: the KeyfileKey object as returned by
  89. attic.key.KeyfileKey.create()
  90. """
  91. keys_dir = str(tmpdir.mkdir('keys'))
  92. # we use the repo dir for the created keyfile, because we do
  93. # not want to clutter existing keyfiles
  94. os.environ['ATTIC_KEYS_DIR'] = keys_dir
  95. # we use the same directory for the converted files, which
  96. # will clutter the previously created one, which we don't care
  97. # about anyways. in real runs, the original key will be retained.
  98. os.environ['BORG_KEYS_DIR'] = keys_dir
  99. os.environ['ATTIC_PASSPHRASE'] = 'test'
  100. return attic.key.KeyfileKey.create(attic_repo,
  101. MockArgs(keys_dir))
  102. def test_keys(tmpdir, attic_repo, attic_key_file):
  103. """test key conversion
  104. test that we can convert the given key to a properly formatted
  105. borg key. assumes that the ATTIC_KEYS_DIR and BORG_KEYS_DIR have
  106. been properly populated by the attic_key_file fixture.
  107. :param tmpdir: a temporary directory (a builtin fixture)
  108. :param attic_repo: an attic.repository.Repository object (fixture
  109. define above)
  110. :param attic_key_file: an attic.key.KeyfileKey (fixture created above)
  111. """
  112. repository = AtticRepositoryUpgrader(str(tmpdir), create=False)
  113. keyfile = AtticKeyfileKey.find_key_file(repository)
  114. AtticRepositoryUpgrader.convert_keyfiles(keyfile, dryrun=False)
  115. assert key_valid(attic_key_file.path)
  116. def test_convert_all(tmpdir, attic_repo, attic_key_file):
  117. """test all conversion steps
  118. this runs everything. mostly redundant test, since everything is
  119. done above. yet we expect a NotImplementedError because we do not
  120. convert caches yet.
  121. :param tmpdir: a temporary directory (a builtin fixture)
  122. :param attic_repo: an attic.repository.Repository object (fixture
  123. define above)
  124. :param attic_key_file: an attic.key.KeyfileKey (fixture created above)
  125. """
  126. # check should fail because of magic number
  127. assert not repo_valid(tmpdir)
  128. logger.info("opening attic repository with borg and converting")
  129. repo = AtticRepositoryUpgrader(str(tmpdir), create=False)
  130. repo.upgrade(dryrun=False)
  131. assert key_valid(attic_key_file.path)
  132. assert repo_valid(tmpdir)