90 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/python3
 | |
| 
 | |
| import hashlib
 | |
| import json
 | |
| import os
 | |
| import subprocess
 | |
| import sys
 | |
| 
 | |
| from cryptography.hazmat.backends import default_backend
 | |
| from cryptography.hazmat.primitives import hashes
 | |
| from cryptography.hazmat.primitives.asymmetric import ec
 | |
| from cryptography.hazmat.primitives.serialization import load_pem_private_key
 | |
| 
 | |
| BUILD_ROOT = '/srv/build/lxc'
 | |
| PRIVATE_KEY = '/srv/build/packages.key'
 | |
| LXC_ROOT = '/var/lib/lxc'
 | |
| 
 | |
| def pack(pkg_file):
 | |
|     if os.path.isdir(pkg_file):
 | |
|         pkg_file = os.path.join(pkg_file, 'pkg')
 | |
|     # Prepare metadata
 | |
|     meta = {}
 | |
|     with open(pkg_file) as f:
 | |
|         for line in f:
 | |
|             line = [l.strip() for l in line.split(':', 1)]
 | |
|             meta[line[0]] = line[1]
 | |
|     meta['deps'] = meta['deps'].split()
 | |
|     pkg_name = meta['pkg']
 | |
|     del meta['pkg']
 | |
| 
 | |
|     tar_path = os.path.join(BUILD_ROOT, '{}.tar'.format(pkg_name))
 | |
|     xz_path = '{}.xz'.format(tar_path)
 | |
| 
 | |
|     # Remove old package
 | |
|     if os.path.exists(tar_path):
 | |
|         os.unlink(tar_path)
 | |
|     if os.path.exists(xz_path):
 | |
|         os.unlink(xz_path)
 | |
| 
 | |
|     # Create archive
 | |
|     print('Archiving', meta['lxcpath'])
 | |
|     subprocess.run(['tar', '--xattrs', '-cpf', tar_path, os.path.join(LXC_ROOT, meta['lxcpath'])], cwd='/')
 | |
|     if '/' not in meta['lxcpath']:
 | |
|         # If lxcpath doesn't point to layer but is a full-featured container, pack also scripts
 | |
|         print('Archiving install/upgrade/uninstall scripts and related files')
 | |
|         cwd = os.path.dirname(os.path.abspath(pkg_file))
 | |
|         subprocess.run(['tar', '--transform', 's|^|srv/{}/|'.format(pkg_name), '-rpf', tar_path, 'install', 'install.sh', 'upgrade', 'upgrade.sh', 'uninstall', 'uninstall.sh'], cwd=cwd)
 | |
|     # Compress the tarball with xz (LZMA2)
 | |
|     print('Compressing', tar_path, '({:.2f} MB)'.format(os.path.getsize(tar_path)/1048576))
 | |
|     subprocess.run(['xz', '-9', tar_path])
 | |
|     print('Compressed ', xz_path, '({:.2f} MB)'.format(os.path.getsize(xz_path)/1048576))
 | |
| 
 | |
|     # Register package
 | |
|     print('Registering package')
 | |
|     packages = {}
 | |
|     packages_file = os.path.join(BUILD_ROOT, 'packages')
 | |
|     if os.path.exists(packages_file):
 | |
|         with open(packages_file, 'r') as f:
 | |
|             packages = json.load(f)
 | |
|     packages[pkg_name] = meta
 | |
|     packages[pkg_name]['size'] = os.path.getsize(xz_path)
 | |
|     packages[pkg_name]['sha512'] = hash_file(xz_path)
 | |
|     with open(packages_file, 'w') as f:
 | |
|         json.dump(packages, f, sort_keys=True, indent=4)
 | |
| 
 | |
|     # Sign packages
 | |
|     print('Signing packages')
 | |
|     with open(PRIVATE_KEY, 'rb') as f:
 | |
|         priv_key = load_pem_private_key(f.read(), None, default_backend())
 | |
|     with open(os.path.join(BUILD_ROOT, 'packages'), 'rb') as f:
 | |
|         data = f.read()
 | |
|     with open(os.path.join(BUILD_ROOT, 'packages.sig'), 'wb') as f:
 | |
|         f.write(priv_key.sign(data, ec.ECDSA(hashes.SHA512())))
 | |
| 
 | |
| def hash_file(file_path):
 | |
|     sha512 = hashlib.sha512()
 | |
|     with open(file_path, 'rb') as f:
 | |
|         while True:
 | |
|             data = f.read(65536)
 | |
|             if not data:
 | |
|                 break
 | |
|             sha512.update(data)
 | |
|     return sha512.hexdigest()
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     if len(sys.argv) != 2:
 | |
|         print('Usage: lxc-pack <pkgfile>')
 | |
|     else:
 | |
|         pack(sys.argv[1])
 |