summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcopy_qxl_to_image183
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)