virt-back 0.2.4__tar.gz → 0.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: virt-back
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: virt-back: A backup utility for QEMU, KVM, XEN, and Virtualbox guests
5
5
  Home-page: https://git.unturf.com/python/virt-back
6
6
  Author: Russell Ballestrini
@@ -9,6 +9,17 @@ License: Public Domain
9
9
  Keywords: backup virtual hypervisor QEMU KVM XEN Virtualbox
10
10
  Platform: All
11
11
  Description-Content-Type: text/markdown
12
+ Requires-Dist: libvirt-python
13
+ Dynamic: author
14
+ Dynamic: author-email
15
+ Dynamic: description
16
+ Dynamic: description-content-type
17
+ Dynamic: home-page
18
+ Dynamic: keywords
19
+ Dynamic: license
20
+ Dynamic: platform
21
+ Dynamic: requires-dist
22
+ Dynamic: summary
12
23
 
13
24
  A backup utility for QEMU, KVM, XEN, and Virtualbox guests.
14
25
 
@@ -39,6 +50,7 @@ options:
39
50
  -g, --no-gzip do not gzip the resulting tar file
40
51
  -a amount, --retention amount
41
52
  backups to retain [default: 3]
53
+ (applies to both rotated backup files AND ZFS @backup-* snapshots)
42
54
  -p 'PATH', --path 'PATH'
43
55
  backup path [default: '/KVMBACK']
44
56
  -u 'URI', --uri 'URI'
@@ -27,6 +27,7 @@ options:
27
27
  -g, --no-gzip do not gzip the resulting tar file
28
28
  -a amount, --retention amount
29
29
  backups to retain [default: 3]
30
+ (applies to both rotated backup files AND ZFS @backup-* snapshots)
30
31
  -p 'PATH', --path 'PATH'
31
32
  backup path [default: '/KVMBACK']
32
33
  -u 'URI', --uri 'URI'
@@ -0,0 +1,71 @@
1
+ from setuptools import setup
2
+ import os
3
+
4
+ # Read the contents of your README file
5
+ with open(os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8") as f:
6
+ long_description = f.read()
7
+
8
+ setup(
9
+ name="virt-back",
10
+ version="0.2.5",
11
+ description="virt-back: A backup utility for QEMU, KVM, XEN, and Virtualbox guests",
12
+ keywords="backup virtual hypervisor QEMU KVM XEN Virtualbox",
13
+ long_description=long_description,
14
+ long_description_content_type="text/markdown",
15
+ author="Russell Ballestrini",
16
+ author_email="russell@ballestrini.net",
17
+ url="https://git.unturf.com/python/virt-back",
18
+ platforms=["All"],
19
+ license="Public Domain",
20
+ py_modules=["virtback"],
21
+ include_package_data=True,
22
+ scripts=["virt-back"],
23
+ install_requires=[
24
+ "libvirt-python",
25
+ ],
26
+ )
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Release process (automated via .gitlab-ci.yml on tag push)
30
+ # ---------------------------------------------------------------------------
31
+ #
32
+ # Cutting a release:
33
+ # 1. Bump `version=` above
34
+ # 2. git commit -m "X.Y.Z: <one-line summary>"
35
+ # 3. git tag -a X.Y.Z -m "X.Y.Z"
36
+ # 4. git push origin master X.Y.Z
37
+ #
38
+ # The CI pipeline builds (python -m build) and uploads (twine upload) on the
39
+ # tag push. No manual `python setup.py sdist && twine upload` needed.
40
+ #
41
+ # ---------------------------------------------------------------------------
42
+ # Maintainer setup (one-time, per project) — required for CI uploads to work
43
+ # ---------------------------------------------------------------------------
44
+ #
45
+ # git.unturf.com -> python/<this-project> -> Settings -> Repository ->
46
+ # Protected Tags -> "Protect tag":
47
+ # - Pattern: *
48
+ # - Allowed to Create: Maintainers (match erldistpy's setting)
49
+ #
50
+ # This makes tags Protected refs, which lets the Protected/Masked
51
+ # TWINE_USERNAME and TWINE_PASSWORD variables (set once at the python/
52
+ # group level) reach the tag pipeline. Without Protected Tags, twine 6
53
+ # falls through to OIDC trusted publishing and fails because PyPI's
54
+ # self-hosted GitLab support is hardcoded to gitlab.com.
55
+ #
56
+ # Group variables live at:
57
+ # git.unturf.com -> python (group) -> Settings -> CI/CD -> Variables
58
+ # TWINE_USERNAME = __token__
59
+ # TWINE_PASSWORD = <pypi-AgEI...> (Masked + Protected)
60
+ #
61
+ # setuptools keyword args: http://peak.telecommunity.com/DevCenter/setuptools
62
+
63
+ # Installation Instructions:
64
+ # To install virt-back, you can use pip:
65
+ # * pip install virt-back
66
+ #
67
+ # Note: You need to have the libvirt development libraries installed.
68
+ # On Fedora/RedHat, you can install it with:
69
+ # * sudo dnf install libvirt-devel
70
+ # On Ubuntu, you can install it with:
71
+ # * sudo apt-get install libvirt-dev
@@ -195,6 +195,9 @@ def backup(doms):
195
195
  except subprocess.CalledProcessError as e:
196
196
  logit("error", f"Failed to send ZFS snapshot {zfs_snapshot}: {e}")
197
197
  continue
198
+
199
+ # Prune old @backup-* snapshots, keep newest `retention`
200
+ prune_zfs_snapshots(zfs_dataset, options.retention)
198
201
  else:
199
202
  # Handle QCOW2 or other file-based disk
200
203
  logit("backup", f"{disk_source} is not a ZFS dataset")
@@ -281,6 +284,42 @@ def is_zfs_dataset(disk_source):
281
284
  return False
282
285
 
283
286
 
287
+ def prune_zfs_snapshots(zfs_dataset, retention):
288
+ """List @backup-* snapshots on dataset, destroy oldest until count <= retention.
289
+
290
+ Only touches snapshots virt-back created (@backup-* prefix). Never destroys
291
+ user or TrueNAS periodic snapshots. Never destroys more than necessary —
292
+ `retention` snapshots always survive as the recovery floor.
293
+ """
294
+ if retention < 1:
295
+ logit("error", f"retention must be >= 1, got {retention} — skipping prune")
296
+ return
297
+
298
+ try:
299
+ result = subprocess.run(
300
+ ["zfs", "list", "-t", "snapshot", "-H", "-o", "name",
301
+ "-s", "creation", zfs_dataset],
302
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, text=True,
303
+ )
304
+ except subprocess.CalledProcessError as e:
305
+ logit("error", f"Failed to list snapshots for {zfs_dataset}: {e}")
306
+ return
307
+
308
+ prefix = f"{zfs_dataset}@backup-"
309
+ snaps = [line for line in result.stdout.splitlines() if line.startswith(prefix)]
310
+
311
+ surplus = len(snaps) - retention
312
+ if surplus <= 0:
313
+ return
314
+
315
+ for snap in snaps[:surplus]:
316
+ logit("backup", f"pruning old ZFS snapshot {snap} (retention={retention})")
317
+ try:
318
+ subprocess.run(["zfs", "destroy", snap], check=True)
319
+ except subprocess.CalledProcessError as e:
320
+ logit("error", f"Failed to destroy snapshot {snap}: {e}")
321
+
322
+
284
323
  def shutdown(doms, wait=180):
285
324
  """Accept a list of dom objects, attempt to shutdown the active ones"""
286
325
  # get all running guests from list and invoke shutdown
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: virt-back
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: virt-back: A backup utility for QEMU, KVM, XEN, and Virtualbox guests
5
5
  Home-page: https://git.unturf.com/python/virt-back
6
6
  Author: Russell Ballestrini
@@ -9,6 +9,17 @@ License: Public Domain
9
9
  Keywords: backup virtual hypervisor QEMU KVM XEN Virtualbox
10
10
  Platform: All
11
11
  Description-Content-Type: text/markdown
12
+ Requires-Dist: libvirt-python
13
+ Dynamic: author
14
+ Dynamic: author-email
15
+ Dynamic: description
16
+ Dynamic: description-content-type
17
+ Dynamic: home-page
18
+ Dynamic: keywords
19
+ Dynamic: license
20
+ Dynamic: platform
21
+ Dynamic: requires-dist
22
+ Dynamic: summary
12
23
 
13
24
  A backup utility for QEMU, KVM, XEN, and Virtualbox guests.
14
25
 
@@ -39,6 +50,7 @@ options:
39
50
  -g, --no-gzip do not gzip the resulting tar file
40
51
  -a amount, --retention amount
41
52
  backups to retain [default: 3]
53
+ (applies to both rotated backup files AND ZFS @backup-* snapshots)
42
54
  -p 'PATH', --path 'PATH'
43
55
  backup path [default: '/KVMBACK']
44
56
  -u 'URI', --uri 'URI'
@@ -195,6 +195,9 @@ def backup(doms):
195
195
  except subprocess.CalledProcessError as e:
196
196
  logit("error", f"Failed to send ZFS snapshot {zfs_snapshot}: {e}")
197
197
  continue
198
+
199
+ # Prune old @backup-* snapshots, keep newest `retention`
200
+ prune_zfs_snapshots(zfs_dataset, options.retention)
198
201
  else:
199
202
  # Handle QCOW2 or other file-based disk
200
203
  logit("backup", f"{disk_source} is not a ZFS dataset")
@@ -281,6 +284,42 @@ def is_zfs_dataset(disk_source):
281
284
  return False
282
285
 
283
286
 
287
+ def prune_zfs_snapshots(zfs_dataset, retention):
288
+ """List @backup-* snapshots on dataset, destroy oldest until count <= retention.
289
+
290
+ Only touches snapshots virt-back created (@backup-* prefix). Never destroys
291
+ user or TrueNAS periodic snapshots. Never destroys more than necessary —
292
+ `retention` snapshots always survive as the recovery floor.
293
+ """
294
+ if retention < 1:
295
+ logit("error", f"retention must be >= 1, got {retention} — skipping prune")
296
+ return
297
+
298
+ try:
299
+ result = subprocess.run(
300
+ ["zfs", "list", "-t", "snapshot", "-H", "-o", "name",
301
+ "-s", "creation", zfs_dataset],
302
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, text=True,
303
+ )
304
+ except subprocess.CalledProcessError as e:
305
+ logit("error", f"Failed to list snapshots for {zfs_dataset}: {e}")
306
+ return
307
+
308
+ prefix = f"{zfs_dataset}@backup-"
309
+ snaps = [line for line in result.stdout.splitlines() if line.startswith(prefix)]
310
+
311
+ surplus = len(snaps) - retention
312
+ if surplus <= 0:
313
+ return
314
+
315
+ for snap in snaps[:surplus]:
316
+ logit("backup", f"pruning old ZFS snapshot {snap} (retention={retention})")
317
+ try:
318
+ subprocess.run(["zfs", "destroy", snap], check=True)
319
+ except subprocess.CalledProcessError as e:
320
+ logit("error", f"Failed to destroy snapshot {snap}: {e}")
321
+
322
+
284
323
  def shutdown(doms, wait=180):
285
324
  """Accept a list of dom objects, attempt to shutdown the active ones"""
286
325
  # get all running guests from list and invoke shutdown
virt-back-0.2.4/setup.py DELETED
@@ -1,47 +0,0 @@
1
- from setuptools import setup
2
- import os
3
-
4
- # Read the contents of your README file
5
- with open(os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8") as f:
6
- long_description = f.read()
7
-
8
- setup(
9
- name="virt-back",
10
- version="0.2.4",
11
- description="virt-back: A backup utility for QEMU, KVM, XEN, and Virtualbox guests",
12
- keywords="backup virtual hypervisor QEMU KVM XEN Virtualbox",
13
- long_description=long_description,
14
- long_description_content_type="text/markdown",
15
- author="Russell Ballestrini",
16
- author_email="russell@ballestrini.net",
17
- url="https://git.unturf.com/python/virt-back",
18
- platforms=["All"],
19
- license="Public Domain",
20
- py_modules=["virtback"],
21
- include_package_data=True,
22
- scripts=["virt-back"],
23
- install_requires=[
24
- "libvirt-python",
25
- ],
26
- )
27
-
28
- """
29
- setup()
30
- keyword args: http://peak.telecommunity.com/DevCenter/setuptools
31
-
32
- # built and uploaded to pypi with this:
33
-
34
- python setup.py sdist
35
- twine upload dist/*
36
-
37
- """
38
-
39
- # Installation Instructions:
40
- # To install virt-back, you can use pip:
41
- # * pip install virt-back
42
- #
43
- # Note: You need to have the libvirt development libraries installed.
44
- # On Fedora/RedHat, you can install it with:
45
- # * sudo dnf install libvirt-devel
46
- # On Ubuntu, you can install it with:
47
- # * sudo apt-get install libvirt-dev
File without changes