Split client and server code.

This commit is contained in:
Ian Gulliver
2016-03-30 14:29:47 -07:00
parent ca51da3d1f
commit facafa5876
4 changed files with 0 additions and 0 deletions

189
server/build_image.py Executable file
View File

@@ -0,0 +1,189 @@
#!/usr/bin/python3
import argparse
import os
import shutil
import subprocess
import tempfile
parser = argparse.ArgumentParser(description='iconograph build_image')
parser.add_argument(
'--arch',
dest='arch',
action='store',
default='amd64')
parser.add_argument(
'--archive',
dest='archive',
action='store',
default='http://archive.ubuntu.com/ubuntu')
parser.add_argument(
'--dest-iso',
dest='dest_iso',
action='store',
required=True)
parser.add_argument(
'--release',
dest='release',
action='store',
required=True)
parser.add_argument(
'--shell',
dest='shell',
action='store',
type=bool,
default=False)
parser.add_argument(
'--source-iso',
dest='source_iso',
action='store',
required=True)
FLAGS = parser.parse_args()
class ImageBuilder(object):
_BASE_PACKAGES = [
'debconf',
'devscripts',
'dialog',
'gnupg',
'isc-dhcp-client',
'locales',
'nano',
'net-tools',
'iputils-ping',
'sudo',
'user-setup',
'wget',
]
def __init__(self, source_iso, dest_iso, archive, arch, release):
self._source_iso = source_iso
self._dest_iso = dest_iso
self._archive = archive
self._arch = arch
self._release = release
self._umount = []
self._rmtree = []
def _Exec(self, *args):
print('+', args)
subprocess.check_call(args)
def _ExecChroot(self, chroot_path, *args):
self._Exec('chroot', chroot_path, *args)
def _Debootstrap(self, root):
path = os.path.join(root, 'chroot')
os.mkdir(path)
self._Exec(
'debootstrap',
'--variant=buildd',
'--arch', self._arch,
self._release,
path,
self._archive)
return path
def _CreateUnion(self, root):
iso_path = os.path.join(root, 'iso')
os.mkdir(iso_path)
self._Exec(
'mount',
'--options', 'loop,ro',
self._source_iso,
iso_path)
self._umount.append(iso_path)
tmpfs_path = os.path.join(root, 'tmpfs')
os.mkdir(tmpfs_path)
self._Exec(
'mount',
'--types', 'tmpfs',
'none',
tmpfs_path)
self._umount.append(tmpfs_path)
upper_path = os.path.join(tmpfs_path, 'upper')
os.mkdir(upper_path)
work_path = os.path.join(tmpfs_path, 'work')
os.mkdir(work_path)
union_path = os.path.join(root, 'union')
os.mkdir(union_path)
self._Exec(
'mount',
'--types', 'overlayfs',
'--options', 'lowerdir=%s,upperdir=%s,workdir=%s' % (iso_path, upper_path, work_path),
'none',
union_path)
self._umount.append(union_path)
return union_path
def _InstallPackages(self, chroot_path):
self._ExecChroot(
chroot_path,
'apt-get',
'install',
'--assume-yes',
*self._BASE_PACKAGES)
self._ExecChroot(
chroot_path,
'apt-get',
'clean')
def _Squash(self, chroot_path, union_path):
self._Exec(
'mksquashfs',
chroot_path,
os.path.join(union_path, 'casper', 'filesystem.squashfs'),
'-noappend')
def _CreateISO(self, union_path):
self._Exec(
'grub-mkrescue',
'--verbose',
'--output=%s' % self._dest_iso,
union_path)
def _BuildImage(self):
root = tempfile.mkdtemp()
self._rmtree.append(root)
print('Building image in:', root)
chroot_path = self._Debootstrap(root)
union_path = self._CreateUnion(root)
self._InstallPackages(chroot_path)
if FLAGS.shell:
self._Exec('bash')
self._Squash(chroot_path, union_path)
self._CreateISO(union_path)
def BuildImage(self):
try:
self._BuildImage()
finally:
pass
for path in self._umount:
self._Exec('umount', path)
for path in self._rmtree:
shutil.rmtree(path)
def main():
builder = ImageBuilder(
FLAGS.source_iso,
FLAGS.dest_iso,
FLAGS.archive,
FLAGS.arch,
FLAGS.release)
builder.BuildImage()
if __name__ == '__main__':
main()

90
server/build_manifest.py Executable file
View File

@@ -0,0 +1,90 @@
#!/usr/bin/python3
import argparse
import hashlib
import json
import os
import re
import sys
import time
parser = argparse.ArgumentParser(description='iconograph fetcher')
parser.add_argument(
'--image-dir',
dest='image_dir',
action='store',
required=True)
parser.add_argument(
'--image-type',
dest='image_type',
action='store',
required=True)
parser.add_argument(
'--old-manifest',
dest='old_manifest',
action='store')
FLAGS = parser.parse_args()
class ManifestBuilder(object):
_FILE_REGEX = '^%(image_type)s\.(?P<timestamp>\d+)\.iso$'
_BUF_SIZE = 2 ** 16
def __init__(self, image_dir, image_type, old_manifest):
self._image_dir = image_dir
self._file_regex = re.compile(self._FILE_REGEX % {
'image_type': image_type,
})
self._old_manifest = old_manifest
def _Rollouts(self):
if not self._old_manifest:
return {}
try:
with open(self._old_manifest, 'r') as fh:
parsed = json.load(fh)
return dict(
(image['timestamp'], image['rollout_‱'])
for image in parsed['images'])
except FileNotFoundError:
return {}
def BuildManifest(self):
ret = {
'timestamp': int(time.time()),
'images': [],
}
rollouts = self._Rollouts()
for filename in os.listdir(self._image_dir):
match = self._file_regex.match(filename)
if not match:
continue
timestamp = int(match.group('timestamp'))
image = {
'timestamp': timestamp,
'rollout_‱': rollouts.get(timestamp, 0),
}
with open(os.path.join(self._image_dir, filename), 'rb') as fh:
hash_obj = hashlib.sha256()
while True:
data = fh.read(self._BUF_SIZE)
if not data:
break
hash_obj.update(data)
image['hash'] = hash_obj.hexdigest()
ret['images'].append(image)
ret['images'].sort(key=lambda x: x['timestamp'], reverse=True)
return ret
def main():
builder = ManifestBuilder(FLAGS.image_dir, FLAGS.image_type, FLAGS.old_manifest)
manifest = builder.BuildManifest()
json.dump(manifest, sys.stdout, sort_keys=True, indent=4)
sys.stdout.write('\n')
if __name__ == '__main__':
main()

60
server/wrap_file.py Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/python3
import argparse
import codecs
import json
from OpenSSL import crypto
import sys
parser = argparse.ArgumentParser(description='iconograph wrap_file')
parser.add_argument(
'--cert',
dest='cert',
action='store',
required=True)
parser.add_argument(
'--key',
dest='key',
action='store',
required=True)
parser.add_argument(
'--other-cert',
dest='other_certs',
action='store',
nargs='*')
FLAGS = parser.parse_args()
class Wrapper(object):
def __init__(self, key, cert, other_certs):
with open(key, 'r') as fh:
self._key = crypto.load_privatekey(crypto.FILETYPE_PEM, fh.read())
with open(cert, 'r') as fh:
self._cert_str = fh.read()
self._cert = crypto.load_certificate(crypto.FILETYPE_PEM, self._cert_str)
self._other_cert_strs = []
for path in (other_certs or []):
with open(path, 'r') as fh:
self._other_cert_strs.append(fh.read())
def Wrap(self, instr):
inbytes = instr.encode('utf8')
return {
'cert': self._cert_str,
'other_certs': self._other_cert_strs,
'sig': codecs.encode(crypto.sign(self._key, inbytes, 'sha256'), 'hex').decode('ascii'),
'inner': instr,
}
def main():
wrapper = Wrapper(FLAGS.key, FLAGS.cert, FLAGS.other_certs)
wrapped = wrapper.Wrap(sys.stdin.read())
json.dump(wrapped, sys.stdout, sort_keys=True, indent=4)
sys.stdout.write('\n')
if __name__ == '__main__':
main()