# HG changeset patch # User tjd21@xxxxxxxxxxxxxxxxxxxxxx # Node ID e35449fc66de226857fbf7946b2cccadbff23dd7 # Parent c4ae9456a4595f046f08aea2f2e7b3664b50ab82 Added "guest:(dev)/path/to/file" syntax to xm create filenames Added pyfscat script to pygrub, needed for guest: syntax Signed-off-by: Tim Deegan diff -r c4ae9456a459 -r e35449fc66de tools/pygrub/setup.py --- a/tools/pygrub/setup.py Fri Jan 20 19:31:09 2006 +++ b/tools/pygrub/setup.py Mon Jan 23 13:31:25 2006 @@ -43,7 +43,7 @@ author_email='katzj@xxxxxxxxxx', license='GPL', package_dir={'grub': 'src'}, - scripts = ["src/pygrub"], + scripts = ["src/pygrub", "src/pyfscat"], packages=pkgs, ext_modules = fsys_mods ) diff -r c4ae9456a459 -r e35449fc66de tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Fri Jan 20 19:31:09 2006 +++ b/tools/python/xen/xm/create.py Mon Jan 23 13:31:25 2006 @@ -26,6 +26,8 @@ import socket import commands import time +import re +import tempfile import xen.lowlevel.xc @@ -396,6 +398,9 @@ fn=set_value, default=None, use="X11 Authority to use") +gopts.var('delete_after', val='FILES', + fn=append_value, default=[], + use="Files to delete after domain starts") def err(msg): """Print an error to stderr and exit. @@ -418,13 +423,58 @@ else: return s +def file_from_guest(file, vals): + """Extract a file from one of the guest disk images. + """ + if len(vals.disk) < 1: + err("No disks configured and guest-fs file requested") + m = re.match('^\(([^)]+)\)(.*)$', file) + partno = 0 + if m != None: + dev = m.group(1) + file = m.group(2) + m = re.match('^([^0-9]+)([0-9]+)$', dev) + if m != None: + dev = m.group(1) + partno = int(m.group(2)) + dev_uname = None + for disk in vals.disk: + (uname, vdev, _, _) = disk + if dev == vdev: + dev_uname = uname + break + if dev_uname == None: + err("Can't find guest block dev %s to extract %s" % (dev, file)) + else: + (dev_uname, _, _, _) = vals.disk[0] + dev_file = blkif.blkdev_uname_to_file(dev_uname) + if dev_file == None: + err("Can't find guest disk image %s to extract %s" % (dev_uname, file)) + (tfd, fname) = tempfile.mkstemp() + os.close(tfd) + rv = os.system("pyfscat -q -p %i %s %s %s" + % (partno, dev_file, file, fname)) + if rv != 0: + os.unlink(fname) + err("Can't extract %s from guest disk image %s" % (file, dev_uname)) + vals.delete_after.append(fname) + return fname + +def parse_filename(file, vals): + """Parse filename for 'guest:' format + """ + if file.startswith("guest:"): + return file_from_guest(file[6:], vals) + else: + return os.path.abspath(file) + def configure_image(vals): """Create the image config. """ config_image = [ vals.builder ] - config_image.append([ 'kernel', os.path.abspath(vals.kernel) ]) + config_image.append([ 'kernel', parse_filename(vals.kernel, vals) ]) if vals.ramdisk: - config_image.append([ 'ramdisk', os.path.abspath(vals.ramdisk) ]) + config_image.append([ 'ramdisk', parse_filename(vals.ramdisk, vals) ]) if vals.cmdline_ip: cmdline_ip = strip('ip=', vals.cmdline_ip) config_image.append(['ip', cmdline_ip]) @@ -795,6 +845,10 @@ server.xend_domain_destroy(dom) err("Failed to unpause domain %s" % dom) opts.info("Started domain %s" % (dom)) + + for file in opts.vals.delete_after: + os.unlink(file) + return int(sxp.child_value(dominfo, 'domid')) def parseCommandLine(argv): diff -r c4ae9456a459 -r e35449fc66de tools/pygrub/src/pyfscat --- /dev/null Fri Jan 20 19:31:09 2006 +++ b/tools/pygrub/src/pyfscat Mon Jan 23 13:31:25 2006 @@ -0,0 +1,169 @@ +#!/usr/bin/python +# +# pyfscat - extract a file's contents from a filesystem image. +# +# Copyright (C) 2005 XenSource Ltd +# +# Based on pygrub, Copyright 2005 Red Hat, Inc. +# Jeremy Katz +# +# This software may be freely redistributed under the terms of the GNU +# general public license. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import os, sys, struct, getopt + +sys.path = [ '/usr/lib/python' ] + sys.path + +import grub.fsys + +SECTOR_SIZE=512 + +def get_part_offset(dev_path, quiet, partno): + """Extract a partition offset from a DOS-style partition table. + """ + if partno < 0: + return -1 + if partno == 0: + return 0 + try: + fd = os.open(dev_path, os.O_RDONLY) + buf = os.read(fd, 512) + if (len(buf) < 512 + or struct.unpack("H", buf[0x1fe: 0x200]) != (0xaa55,)): + if not quiet: + print >> sys.stderr, ("No partition table in %s" + % (dev_path)) + return -1 + if partno < 5: + poff = 430 + 16 * partno + offset = (struct.unpack("> sys.stderr, ("Can't find partition %i in %s" + % (partno, dev_path)) + return False + + # Now, call the pygrub libraries to read the file. + fs = None + for fstype in grub.fsys.fstypes.values(): + if fstype.sniff_magic(dev_path, offset): + fs = fstype.open_fs(dev_path, offset) + break + if fs is None: + if not quiet: + print >> sys.stderr, ("Can't open a filesystem image in %s" + % (dev_path)) + return False + if not fs.file_exist(path): + if not quiet: + print >> sys.stderr, ("Can't find file %s in %s" + % (path, dev_path)) + return False + fd = fs.open_file(path, os.O_RDONLY) + contents = fd.read() + + # We have something to write: fix up somewhere to put it + if out_path == "-": + sys.stdout.write(contents) + else: + try: + out_file = open(out_path, 'w') + out_file.write(contents) + out_file.close() + except IOError: + if not quiet: + print >> sys.stderr, "Can't write to %s" % (out_path) + return False + return True + +def usage(): + print >> sys.stderr, ("Usage: %s [-q] [-p n] \n" + "\n" + "Extracts file from fs image " + "to \n" + " -q Don't print error messages\n" + " -p n Use partition number n (in a disk image)\n" + % (sys.argv[0],)) + + +try: + opts, args = getopt.getopt(sys.argv[1:], 'qhp:', + ["quiet", "help", "partno"]) +except getopt.GetoptError: + usage() + sys.exit(1) +if len(args) != 3: + usage() + sys.exit(1) + +quiet = False +partno = 0 +for o, a in opts: + if o in ("-q", "--quiet"): + quiet = True + elif o in ("-h", "--help"): + usage() + sys.exit() + elif o in ("-p", "--partno"): + try: + partno = int(a) + except ValueError: + usage() + sys.exit(1) + if partno < 0: + usage() + sys.exit(1) + +if not file_from_fs_image(args[0], args[1], args[2], quiet, partno): + sys.exit(1)