make_container.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import os
  2. import shutil
  3. import stat
  4. import struct
  5. import subprocess
  6. import sys
  7. import container # 1
  8. def main(output_path, entry_path, input_paths, squashfs_path):
  9. output_tmp_path = output_path + '.tmp'
  10. shutil.copy2(entry_path, output_tmp_path)
  11. st = os.stat(output_tmp_path)
  12. os.chmod(output_tmp_path, st.st_mode | stat.S_IWUSR)
  13. layer_paths = []
  14. other_paths = []
  15. for input_path in input_paths:
  16. (layer_paths if input_path.endswith('.container_layer') else other_paths).append(input_path)
  17. if len(other_paths) == 0:
  18. raise Exception('No program in container dependencies')
  19. if len(other_paths) > 1:
  20. raise Exception('Multiple non-layer inputs')
  21. program_path = other_paths[0]
  22. program_container_path = os.path.basename(program_path)
  23. os.symlink(program_container_path, 'entry')
  24. add_cmd = [os.path.join(squashfs_path, 'mksquashfs')]
  25. add_cmd.extend([program_path, 'entry', 'program_layer'])
  26. subprocess.run(add_cmd)
  27. layer_paths.append('program_layer')
  28. container.join_layers(layer_paths, 'container_data', squashfs_path)
  29. size = 0
  30. block_size = 1024 * 1024
  31. with open(output_tmp_path, 'ab') as output:
  32. with open('container_data', 'rb') as input_:
  33. while True:
  34. data = input_.read(block_size)
  35. output.write(data)
  36. size += len(data)
  37. if len(data) < block_size:
  38. break
  39. with open(os.path.join(squashfs_path, 'unsquashfs'), 'rb') as input_:
  40. while True:
  41. data = input_.read(block_size)
  42. output.write(data)
  43. size += len(data)
  44. if len(data) == 0:
  45. break
  46. output.write(struct.pack('<Q', size))
  47. os.rename(output_tmp_path, output_path)
  48. def entry():
  49. import argparse
  50. parser = argparse.ArgumentParser()
  51. parser.add_argument('-o', '--output', required=True)
  52. parser.add_argument('-s', '--squashfs-path', required=True)
  53. parser.add_argument('input', nargs='*')
  54. args = parser.parse_args()
  55. def is_container_entry(path):
  56. return os.path.basename(path) == '_container_entry'
  57. input_paths = []
  58. entry_paths = []
  59. for input_path in args.input:
  60. (entry_paths if is_container_entry(input_path) else input_paths).append(input_path)
  61. if len(entry_paths) != 1:
  62. raise Exception('Could not select container entry from {}'.format(entry_paths))
  63. return main(args.output, entry_paths[0], input_paths, args.squashfs_path)
  64. if __name__ == '__main__':
  65. sys.exit(entry())