class Unbundler

Public Instance Methods

get_manual() click to toggle source
# File lib/ec2/amitools/unbundle.rb, line 88
def get_manual()
  UNBUNDLE_MANUAL
end
get_name() click to toggle source
# File lib/ec2/amitools/unbundle.rb, line 92
def get_name()
  UNBUNDLE_NAME
end
main(p) click to toggle source
# File lib/ec2/amitools/unbundle.rb, line 96
def main(p)
  unbundle(p)
end
unbundle(p) click to toggle source
# File lib/ec2/amitools/unbundle.rb, line 30
def unbundle(p)
  begin
    manifest_path = p.manifest_path
    src_dir = p.source
    dst_dir = p.destination
    
    digest_pipe = File::join( '/tmp', "ec2-unbundle-image-digest-pipe" )
    File::delete( digest_pipe ) if File::exist?( digest_pipe )
    unless system( "mkfifo #{digest_pipe}" )
      raise "error creating named pipe #{digest_pipe}"
    end
    
    # Load manifest and the user's private key.
    manifest = ManifestV3.new(File.open( manifest_path ) { |f| f.read() })
    pk = Crypto::loadprivkey( p.user_pk_path )
    
    # Extract key and IV from XML manifest.
    key = pk.private_decrypt(Format::hex2bin( manifest.user_encrypted_key))
    iv = pk.private_decrypt(Format::hex2bin( manifest.user_encrypted_iv))
    
    # Create a string of space separated part paths.
    part_files = manifest.parts.collect do |part| 
      File::join( src_dir, part.filename ) 
    end.join( ' ' )
    
    # Join, decrypt, decompress and untar.
    untar = EC2::Platform::Current::Tar::Command.new.extract.chdir(dst_dir)
    pipeline = EC2::Platform::Current::Pipeline.new('image-unbundle-pipeline', @debug)
    pipeline.concat([
                     ['cat', "openssl sha1 < #{digest_pipe} & cat #{part_files}"],
                     ['decrypt', "openssl enc -d -aes-128-cbc -K #{key} -iv #{iv}"],
                     ['gunzip', "gunzip"],
                     ['tee', "tee #{digest_pipe}"],
                     ['untar', untar.expand]
                    ])
    digest = nil
    begin
      digest = pipeline.execute.split(/\s+/).last.strip
    rescue EC2::Platform::Current::Pipeline::ExecutionError => e
      $stderr.puts e.message
    end
    
    # Verify digest.
    unless manifest.digest == digest
      raise "invalid digest, expected #{manifest.digest} received #{digest}"
    end
    
    puts "Unbundle complete."
    return 0
  ensure
    File::delete( digest_pipe ) if (digest_pipe && File::exist?( digest_pipe ))
  end
end