[pkg-eucalyptus-commits] [SCM] managing cloud instances for Eucalyptus branch, master, updated. 3.0.0-alpha3-257-g1da8e3a

Garrett Holmstrom gholms at fedoraproject.org
Sun Jun 16 02:30:59 UTC 2013


The following commit has been merged in the master branch:
commit f4c6037b544da753a2b0f48735f317783e475c66
Author: Garrett Holmstrom <gholms at fedoraproject.org>
Date:   Sun Apr 7 01:03:20 2013 -0700

    WIP on new bundleimage (basic creation works)

diff --git a/euca2ools/commands/bundle/bundleimage2.py b/euca2ools/commands/bundle/bundleimage2.py
new file mode 100644
index 0000000..42d9f38
--- /dev/null
+++ b/euca2ools/commands/bundle/bundleimage2.py
@@ -0,0 +1,164 @@
+#!/usr/bin/python -tt
+
+import argparse
+## TODO:  remove the stuff above and add the regular license header
+import hashlib
+import multiprocessing
+import itertools
+import os.path
+import progressbar
+import random
+import subprocess
+import sys
+import tarfile
+import threading
+import time
+
+
+def _add_fileobj_to_tarball(infile, outfile):
+    tarball = tarfile.open(mode='w|', fileobj=outfile)
+    try:
+        tarinfo = tarfile.TarInfo(os.path.basename(infile.name))
+        tarinfo.size = os.path.getsize(infile.name)
+        tarball.addfile(tarinfo=tarinfo, fileobj=infile)
+    finally:
+        tarball.close()
+
+
+def write_tarball(infile, outfile):
+    widgets = ['Bundling ', progressbar.Bar(), ' ', progressbar.Percentage(),
+               ' ', progressbar.FileTransferSpeed(), ' ', progressbar.ETA()]
+    bar = progressbar.ProgressBar(maxval=os.path.getsize(infile.name),
+                                  widgets=widgets)
+    tar_thread = threading.Thread(target=_add_fileobj_to_tarball,
+                                  args=(infile, outfile))
+    tar_thread.start()
+    bar.start()
+    while tar_thread.is_alive():
+        bar.update(infile.tell())
+        time.sleep(0.25)
+    tar_thread.join()
+    bar.finish()
+
+
+def calc_digest_and_exit(in_fileno, out_fileno, result_pipe):
+    infile = os.fdopen(in_fileno)
+    outfile = os.fdopen(out_fileno, 'w')
+    digest = hashlib.sha1()
+    while True:
+        chunk = infile.read(65536)
+        if chunk:
+            digest.update(chunk)
+            outfile.write(chunk)
+        else:
+            break
+    result_pipe.send(digest.hexdigest())
+    result_pipe.close()
+    infile.close()
+    outfile.close()
+    sys.exit()
+
+
+def bundle_image(image_filename, bundle_filename):
+    # pipe for getting the digest from sha1sum
+    digest_pipe_out, digest_pipe_in = multiprocessing.Pipe(duplex=False)
+    # pipe for getting the part info from the part writer
+    writer_pipe_out, writer_pipe_in = multiprocessing.Pipe(duplex=False)
+    # pipe for tar --> sha1sum
+    tar_out_pipe_out, tar_out_pipe_in = os.pipe()
+    # pipe for sha1sum --> gzip
+    sha_out_pipe_out, sha_out_pipe_in = os.pipe()
+
+    # tar --> sha1sum
+    # Digest calculation is a little more processor-intensive, so it goes in
+    # its own process.
+    # That conveniently lets us avoid the annoyances of passing lots of data
+    # between two threads by letting us simply use OS pipes.
+    pid = os.fork()
+    if pid == 0:
+        digest_pipe_out.close()
+        os.close(tar_out_pipe_in)
+        os.close(sha_out_pipe_out)
+        calc_digest_and_exit(tar_out_pipe_out, sha_out_pipe_in, digest_pipe_in)
+    digest_pipe_in.close()
+    os.close(tar_out_pipe_out)
+    os.close(sha_out_pipe_in)
+
+    # sha1sum --> gzip
+    try:
+        gzip = subprocess.Popen(['pigz', '-c'], stdin=sha_out_pipe_out,
+                                stdout=subprocess.PIPE, close_fds=True,
+                                bufsize=-1)
+    except OSError:
+        gzip = subprocess.Popen(['gzip', '-c'], stdin=sha_out_pipe_out,
+                                stdout=subprocess.PIPE, close_fds=True,
+                                bufsize=-1)
+    os.close(sha_out_pipe_out)
+
+    # gzip --> openssl
+    srand = random.SystemRandom()
+    key = format(srand.getrandbits(128), 'x')
+    iv = format(srand.getrandbits(128), 'x')
+    openssl = subprocess.Popen(['openssl', 'enc', '-e', '-aes-128-cbc',
+                                '-K', key, '-iv', iv], stdin=gzip.stdout,
+                               stdout=subprocess.PIPE, close_fds=True,
+                               bufsize=-1)
+
+    # openssl --> writer
+    writer_thread = threading.Thread(target=write_parts,
+                                     args=(openssl.stdout, bundle_filename,
+                                           writer_pipe_in))
+    writer_thread.start()
+
+    # Drive everything by feeding tar
+    with open(image_filename) as image:
+        with os.fdopen(tar_out_pipe_in, 'w') as tar_input:
+            write_tarball(image, tar_input)
+        writer_thread.join()
+
+        digest = digest_pipe_out.recv()
+        digest_pipe_out.close()
+        parts = writer_pipe_out.recv()
+        writer_pipe_out.close()
+    return (parts, digest, key, iv)
+
+
+PART_SIZE = 1024 * 1024
+
+
+def write_parts(infile, part_prefix, result_pipe):
+    parts = []
+    for part_no in itertools.count():
+        part_fname = '{0}.part.{1}'.format(part_prefix, part_no)
+        print 'Writing part', part_fname
+        part_info = _write_single_part(infile, part_fname)
+        parts.append(part_info)
+        if part_info['size'] < PART_SIZE:
+            # That's the last part
+            result_pipe.send(parts)
+            return
+
+
+def _write_single_part(infile, part_fname):
+    part_digest = hashlib.sha1()
+    with open(part_fname, 'w') as part:
+        bytes_to_write = PART_SIZE
+        while bytes_to_write > 0:
+            chunk = infile.read(min((bytes_to_write, 65536)))
+            if chunk:
+                part.write(chunk)
+                part_digest.update(chunk)
+                bytes_to_write -= len(chunk)
+            else:
+                break
+        return {'path': part_fname, 'digest': part_digest.hexdigest(),
+                'size': part.tell()}
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument('image_filename')
+    parser.add_argument('bundle_filename')
+    args = parser.parse_args()
+    result = bundle_image(args.image_filename, args.bundle_filename)
+    print result

-- 
managing cloud instances for Eucalyptus



More information about the pkg-eucalyptus-commits mailing list