diff options
Diffstat (limited to 'copy_qxl_to_image')
-rwxr-xr-x | copy_qxl_to_image | 183 |
1 files changed, 140 insertions, 43 deletions
diff --git a/copy_qxl_to_image b/copy_qxl_to_image index 3e9004b..89b651a 100755 --- a/copy_qxl_to_image +++ b/copy_qxl_to_image @@ -4,6 +4,10 @@ import argparse import sys import os import subprocess +import zipfile +import guestfs +import tempfile +import tarfile parser = argparse.ArgumentParser() parser.add_argument('--image', dest='image', default=None) @@ -12,6 +16,9 @@ parser.add_argument('--partition', dest='partition', default=None) parser.add_argument('--system32', dest='system32', choices=['Windows/System32', 'WINDOWS/system32']) parser.add_argument('--erase_old_driver_files', dest='erase', default=False, action='store_true') parser.add_argument('--allow-old', action='store_true', default=False) +parser.add_argument('--brew') +parser.add_argument('--arch', choices=['x86', 'x64']) +parser.add_argument('--winver', choices=['w7', 'xp']) args, rest = parser.parse_known_args(sys.argv[1:]) if os.system('which guestfish'): @@ -22,35 +29,142 @@ def no_flags_usage(rest): if len(rest) != 4: parser.print_usage() sys.exit(1) + # do this via argparse?? if not args.image: no_flags_usage(rest) args.image = rest[0] -if not args.root: +if not args.root and not args.brew: no_flags_usage(rest) args.root = rest[1] -if not args.partition: +if not args.partition and not args.winver: no_flags_usage(rest) args.partition = rest[2] if not args.system32: args.system32 = 'WINDOWS/system32' if (len(rest) != 4) else rest[3] -base=os.path.dirname(args.image) -qxldd_path = os.path.realpath(os.path.join(args.root, 'qxldd.dll')) -if not os.path.exists(qxldd_path): - print "missing qxldd.dll" - sys.exit(1) -qxlsys_path = os.path.realpath(os.path.join(args.root, 'qxl.sys')) -if not os.path.exists(qxlsys_path): - print "missing qxl.sys" - sys.exit(1) -if not os.path.exists(args.image): - print "provided image does not exist" - sys.exit(1) -image_user = os.popen("lsof -t %s" % args.image).read().strip() -if len(image_user) != 0: - print "image is being used by %s" % image_user - print "will not update used image" - sys.exit(1) +if args.winver: + # override system32 logic before + args.system32 = 'Windows/System32' if args.winver == 'w7' else 'WINDOWS/system32' + if not args.partition: + args.partition = 2 if args.winver == 'w7' else 1 + +HOME = os.environ['HOME'] +BREW_CACHE='%s/.brew_qxl_win_cache' % HOME + +class chdir: + """ usage: + with chdir('/tmp'): + print os.getcwd() # prints '/tmp' + """ + def __init__(self, d): + self.d = d + if not os.path.exists(d): + raise Exception('chdir: no directory %r' % d) + + def __enter__(self, *args, **kw): + self.org = os.getcwd() + os.chdir(self.d) + + def __exit__(self, *args, **kw): + os.chdir(self.org) + +# curl invocation notes: +# -R/--remote-time +# When used, this will make libcurl attempt to figure out the timestamp of the remote file, and if that is available make the local file get that same timestamp. + +def curl(url): + print "downloading %s" % url + os.system('curl -R -O %s' % url) + +def fill_brew_driver_cache(ver, winver, arch, debug=False): + # instead of using the brew utility. can't grok download-latest + assert(winver in ['w7', 'xp']) + assert((winver == 'xp' and arch == 'x86') or arch in ['x86', 'x64']) + driver_path = os.path.join(BREW_CACHE, os.path.join(*ver.split('-'))) + if not os.path.exists(driver_path): + os.makedirs(driver_path) + print "ver = %r" % ver + base_url = 'http://download.devel.redhat.com/brewroot/packages/qxl-win/%s/%s/win/' % tuple(ver.split('-')) + saved_wd = os.getcwd() + with chdir(driver_path): + for mid in ['w7_x86', 'w7_x64', 'xp_x86']: + for post in ['', '_debug']: + filename = 'qxl_%s%s.zip' % (mid, post) + target = os.path.join(driver_path, filename) + if not os.path.exists(target): + curl(base_url + filename) + if not os.path.exists(target): + print "curl failed?" + sys.exit(1) + return driver_path + '/qxl_%s_%s%s.zip' % (winver, arch, '' if not debug else '_debug') + +def install_brew_driver(args): + """ + get a driver from brew and install in an image + args.brew - version (0.1-8) + args.winver - windows version. TODO - extract from image. + args.arch - architecture. TODO - extract from image + + Unpacks the driver files under the brew cache directory. + TODO - also grab the pdbs? + """ + if not args.winver or not args.arch: + print "missing --arch and --winver" + sys.exit(1) + winver = args.winver + arch = args.arch + zip_filename = fill_brew_driver_cache(ver=args.brew, winver=winver, arch=arch) + zip_dirname = os.path.dirname(zip_filename) + args.root = os.path.join(zip_dirname, args.winver, args.arch) + if not os.path.exists(args.root): + print "unpacking %s" % zip_filename + with chdir(zip_dirname): + zipfile.ZipFile(zip_filename).extractall() + install_driver(args) + +def install_driver(args): + base=os.path.dirname(args.image) + qxldd_path = os.path.realpath(os.path.join(args.root, 'qxldd.dll')) + if not os.path.exists(qxldd_path): + print "missing qxldd.dll" + sys.exit(1) + qxlsys_path = os.path.realpath(os.path.join(args.root, 'qxl.sys')) + if not os.path.exists(qxlsys_path): + print "missing qxl.sys" + sys.exit(1) + if not os.path.exists(args.image): + print "provided image does not exist" + sys.exit(1) + image_user = os.popen("lsof -t %s" % args.image).read().strip() + if len(image_user) != 0: + print "image is being used by %s" % image_user + print "will not update used image" + sys.exit(1) + not_too_old(qxldd_path, not args.allow_old) + not_too_old(qxlsys_path, not args.allow_old) + + print "copying qxl driver %s to %s" % (args.root, args.image) + g = guestfs.GuestFS() + g.set_trace(1) + g.add_drive(args.image) + g.launch() + g.mount("/dev/vda%s" % args.partition, "/") + for local_fname, target_fname in [ + (qxldd_path, '/' + args.system32 + '/qxldd.dll'), + (qxlsys_path, '/' + args.system32 + '/qxlsys.dll')]: + g.upload(local_fname, target_fname) + g.checksum('md5', target_fname) + temp_dir = tempfile.mkdtemp() + tar_name = os.path.join(temp_dir, 'qxl.tar') + with chdir(args.root): + tar = tarfile.open(tar_name, 'w') + tar.add('.') + tar.close() + if not g.exists('/qxl'): + g.mkdir('/qxl') + g.tar_in(tar_name, '/qxl/') + os.system("md5sum %s" % qxldd_path) + os.system("md5sum %s" % qxlsys_path) def not_too_old(p, do_exit): if os.system("peversion %s" % p): @@ -58,33 +172,16 @@ def not_too_old(p, do_exit): if do_exit: sys.exit(1) -not_too_old(qxldd_path, not args.allow_old) -not_too_old(qxlsys_path, not args.allow_old) - -data = dict(system32=args.system32, partition=args.partition, - image=args.image,base=base, qxldd_path=qxldd_path, qxlsys_path=qxlsys_path, - root=args.root) - -# win7 version - vda2 (two ntfs partitions) -guestfish_commands = """add %(image)s -lcd %(base)s -run -mount /dev/vda%(partition)s / -upload %(qxldd_path)s /%(system32)s/qxldd.dll -upload %(qxlsys_path)s /%(system32)s/drivers/qxl.sys -checksum md5 /%(system32)s/qxldd.dll -checksum md5 /%(system32)s/drivers/qxl.sys -""" % data - def guestfish(commands): gf = subprocess.Popen('guestfish', stdin=subprocess.PIPE) gf.stdin.write(commands) gf.stdin.close() return gf.wait() -print "copying qxl driver %(root)s to %(image)s with system32=%(system32)s" % data -if guestfish(guestfish_commands): - print "guestfish_copy failed" - sys.exit(1) -os.system("md5sum %(qxldd_path)s" % data) -os.system("md5sum %(qxlsys_path)s" % data) +if __name__ == '__main__': + # get driver from brew + if args.brew: + args.allow_old = True + install_brew_driver(args) + else: + install_driver(args) |