IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
4.2KB

  1. #
  2. # Copyright (C) Stanislaw Adaszewski, 2020
  3. # License: GNU General Public License v3.0
  4. # URL: https://github.com/sadaszewski/focker
  5. # URL: https://adared.ch/focker
  6. #
  7. from .zfs import *
  8. import os
  9. import yaml
  10. from .steps import create_step
  11. from .snapshot import new_snapshot
  12. from tabulate import tabulate
  13. import subprocess
  14. def build(spec, args):
  15. if 'base' not in spec:
  16. raise ValueError('Missing base in specification')
  17. if 'steps' not in spec:
  18. raise ValueError('Missing steps in specification')
  19. base = spec['base']
  20. base, base_sha256 = zfs_find(base, focker_type='image', zfs_type='snapshot')
  21. root = '/'.join(base.split('/')[:-1])
  22. print('base:', base, 'root:', root)
  23. steps = spec['steps']
  24. if not isinstance(steps, list):
  25. steps = [ steps ]
  26. for st in steps:
  27. st = create_step(st)
  28. st_sha256 = st.hash(base_sha256, args=args)
  29. if zfs_exists_snapshot_sha256(st_sha256):
  30. base = zfs_snapshot_by_sha256(st_sha256)
  31. base_sha256 = st_sha256
  32. print('Reusing:', base)
  33. continue
  34. for pre in range(7, 64):
  35. name = root + '/' + st_sha256[:pre]
  36. if not zfs_exists(name):
  37. break
  38. feed = {
  39. 'focker:sha256': st_sha256
  40. }
  41. def atomic():
  42. st.execute(zfs_mountpoint(name), args=args)
  43. zfs_set_props(name, feed)
  44. snap_name = new_snapshot(base, atomic, name)
  45. # zfs_set_props(name, feed)
  46. # zfs_set_props(snap_name, feed)
  47. base = snap_name
  48. base_sha256 = st_sha256
  49. return (base, base_sha256)
  50. def command_image_build(args):
  51. # os.chdir(args.focker_dir)
  52. fname = os.path.join(args.focker_dir, 'Fockerfile')
  53. print('fname:', fname)
  54. if not os.path.exists(fname):
  55. raise ValueError('No Fockerfile could be found in the specified directory')
  56. with open(fname, 'r') as f:
  57. spec = yaml.safe_load(f)
  58. print('spec:', spec)
  59. image, image_sha256 = build(spec, args)
  60. zfs_untag(args.tags)
  61. zfs_tag(image.split('@')[0], args.tags)
  62. def command_image_tag(args):
  63. zfs_untag(args.tags, focker_type='image')
  64. name, _ = zfs_find(args.reference, focker_type='image', zfs_type='filesystem')
  65. zfs_tag(name, args.tags)
  66. def command_image_untag(args):
  67. zfs_untag(args.tags, focker_type='image')
  68. def command_image_list(args):
  69. lst = zfs_list(fields=['name', 'refer', 'focker:sha256', 'focker:tags', 'origin'],
  70. focker_type='image')
  71. # zfs_parse_output(['zfs', 'list', '-o', 'name,refer,focker:sha256,focker:tags,origin', '-H'])
  72. lst = list(filter(lambda a: a[2] != '-', lst))
  73. lst = list(map(lambda a: [ a[3], a[1],
  74. a[2] if args.full_sha256 else a[2][:7],
  75. a[4].split('/')[-1].split('@')[0] ], lst))
  76. print(tabulate(lst, headers=['Tags', 'Size', 'SHA256', 'Base']))
  77. def command_image_prune(args):
  78. poolname = zfs_poolname()
  79. again = True
  80. while again:
  81. again = False
  82. fields=['focker:sha256', 'focker:tags', 'origin', 'name']
  83. lst = zfs_list(fields=fields, focker_type='image')
  84. lst += zfs_list(fields=fields, focker_type='jail')
  85. # lst = zfs_parse_output(['zfs', 'list', '-o', 'focker:sha256,focker:tags,origin,name', '-H', '-r', poolname + '/focker/images'])
  86. used = set()
  87. for r in lst:
  88. if r[2] == '-':
  89. continue
  90. used.add(r[2].split('@')[0])
  91. for r in lst:
  92. if r[0] == '-' or r[1] != '-':
  93. continue
  94. if r[3] not in used:
  95. print('Removing:', r[3])
  96. zfs_run(['zfs', 'destroy', '-r', '-f', r[3]])
  97. again = True
  98. # zfs_parse_output(['zfs'])
  99. def command_image_remove(args):
  100. snap, snap_sha256 = zfs_find(args.reference, focker_type='image',
  101. zfs_type='snapshot')
  102. ds = snap.split('@')[0]
  103. command = ['zfs', 'destroy', '-r', '-f']
  104. #if args.remove_children:
  105. # command.append('-r')
  106. if args.remove_dependents:
  107. command.append('-R')
  108. command.append(ds)
  109. subprocess.run(command)
  110. # zfs_run(['zfs', 'destroy', ds])