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.

114 lines
4.1KB

  1. import subprocess
  2. from .zfs import *
  3. import random
  4. import shutil
  5. import json
  6. from tabulate import tabulate
  7. def get_jid(path):
  8. data = json.loads(subprocess.check_output(['jls', '--libxo=json']))
  9. lst = data['jail-information']['jail']
  10. lst = list(filter(lambda a: a['path'] == path, lst))
  11. if len(lst) == 0:
  12. raise ValueError('JID not found for path: ' + path)
  13. if len(lst) > 1:
  14. raise ValueError('Ambiguous JID for path: ' + path)
  15. return str(lst[0]['jid'])
  16. def do_mounts(path, mounts):
  17. print('mounts:', mounts)
  18. for (source, target) in mounts:
  19. if source.startswith('/'):
  20. name = source
  21. else:
  22. name, _ = zfs_find(source, focker_type='volume')
  23. name = zfs_mountpoint(name)
  24. while target.startswith('/'):
  25. target = target[1:]
  26. subprocess.check_output(['mount', '-t', 'nullfs', name, os.path.join(path, target)])
  27. def undo_mounts(path, mounts):
  28. for (_, target) in reversed(mounts):
  29. while target.startswith('/'):
  30. target = target[1:]
  31. subprocess.check_output(['umount', '-f', os.path.join(path, target)])
  32. def jail_run(path, command, mounts=[]):
  33. command = ['jail', '-c', 'host.hostname=' + os.path.split(path)[1], 'persist=1', 'mount.devfs=1', 'interface=lo1', 'ip4.addr=127.0.1.0', 'path=' + path, 'command', '/bin/sh', '-c', command]
  34. print('Running:', ' '.join(command))
  35. try:
  36. do_mounts(path, mounts)
  37. shutil.copyfile('/etc/resolv.conf', os.path.join(path, 'etc/resolv.conf'))
  38. res = subprocess.run(command)
  39. finally:
  40. try:
  41. subprocess.run(['jail', '-r', get_jid(path)])
  42. except ValueError:
  43. pass
  44. subprocess.run(['umount', '-f', os.path.join(path, 'dev')])
  45. undo_mounts(path, mounts)
  46. if res.returncode != 0:
  47. # subprocess.run(['umount', os.path.join(path, 'dev')])
  48. raise RuntimeError('Command failed')
  49. def jail_remove(path):
  50. print('Removing jail:', path)
  51. def command_jail_run(args):
  52. base, _ = zfs_snapshot_by_tag_or_sha256(args.image)
  53. # root = '/'.join(base.split('/')[:-1])
  54. for _ in range(10**6):
  55. sha256 = bytes([ random.randint(0, 255) for _ in range(32) ]).hex()
  56. name = sha256[:7]
  57. name = base.split('/')[0] + '/focker/jails/' + name
  58. if not zfs_exists(name):
  59. break
  60. zfs_run(['zfs', 'clone', '-o', 'focker:sha256=' + sha256, base, name])
  61. try:
  62. mounts = list(map(lambda a: a.split(':'), args.mounts))
  63. jail_run(zfs_mountpoint(name), args.command, mounts)
  64. # subprocess.check_output(['jail', '-c', 'interface=lo1', 'ip4.addr=127.0.1.0', 'path=' + zfs_mountpoint(name), 'command', command])
  65. finally:
  66. # subprocess.run(['umount', zfs_mountpoint(name) + '/dev'])
  67. zfs_run(['zfs', 'destroy', '-f', name])
  68. # raise
  69. def command_jail_list(args):
  70. lst = zfs_list(fields=['focker:sha256,focker:tags,mountpoint'], focker_type='jail')
  71. jails = subprocess.check_output(['jls', '--libxo=json'])
  72. jails = json.loads(jails)['jail-information']['jail']
  73. jails = { j['path']: j for j in jails }
  74. lst = list(map(lambda a: [ a[1],
  75. a[0] if args.full_sha256 else a[0][:7],
  76. a[2],
  77. jails[a[2]]['jid'] if a[2] in jails else '-' ], lst))
  78. print(tabulate(lst, headers=['Tags', 'SHA256', 'mountpoint', 'JID']))
  79. def command_jail_tag(args):
  80. name, _ = zfs_find(args.reference, focker_type='jail')
  81. zfs_untag(args.tags, focker_type='jail')
  82. zfs_tag(name, args.tags)
  83. def command_jail_untag(args):
  84. zfs_untag(args.tags, focker_type='jail')
  85. def command_jail_prune(args):
  86. jails = subprocess.check_output(['jls', '--libxo=json'])
  87. jails = json.loads(jails)['jail-information']['jail']
  88. used = set()
  89. for j in jails:
  90. used.add(j['path'])
  91. lst = zfs_list(fields=['focker:sha256,focker:tags,mountpoint,name'], focker_type='jail')
  92. for j in lst:
  93. if j[1] == '-' and j[2] not in used:
  94. jail_remove(j[3])