All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matt Wilson <msw@amazon.com>
To: M A Young <m.a.young@durham.ac.uk>
Cc: Andrew Cooper <Andrew.Cooper3@citrix.com>,
	Ian Campbell <Ian.Campbell@citrix.com>,
	"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Subject: Re: pygrub: avoid problems if guest files are large etc.
Date: Mon, 25 Jun 2012 17:13:21 -0700	[thread overview]
Message-ID: <20120626001321.GC8088@US-SEA-R8XVZTX> (raw)
In-Reply-To: <alpine.DEB.2.00.1206252215180.4133@vega-c.dur.ac.uk>

On Mon, Jun 25, 2012 at 02:34:02PM -0700, M A Young wrote:
> On Mon, 25 Jun 2012, Ian Campbell wrote:
> 
> > BTW, what is the status of that patch?
> 
> I am attaching version 4 of my patch. It moves handling of the kernel and 
> ramdisk into a function along the lines of Miroslav Rezanina's patch
> http://lists.xen.org/archives/html/xen-devel/2012-05/msg01499.html
> It adds checking for problems opening the kernel or ramdisk files and 
> checks they exist in the not_really mode as discussed in this thread.
> 
> I still think it is a good idea to remove the temporary copies of the 
> kernel and ramdisk if there are problems copying them because I am not 
> convinced the calling process always removes them and it might be 
> presented with truncated files if copying the files filled the filespace.
> 
>  	Michael Young
>
> Make pygrub cope better with big files in the guest.
> Only read the first megabyte of a configuration file (grub etc.) and read
> the kernel and ramdisk files from the guest in one megabyte pieces
> so pygrub doesn't use a lot of memory if the files are large.
> With --not-really option check that the chosen kernel and ramdisk files exist.
> If there are problems writing the copy of the kernel or ramdisk, delete the
> copied files and exit in case they have filled the filesystem.
> 
> Signed-off-by: Michael Young <m.a.young@durham.ac.uk>
> 
> --- xen-4.2.0/tools/pygrub/src/pygrub.orig	2012-05-12 16:40:48.000000000 +0100
> +++ xen-4.2.0/tools/pygrub/src/pygrub	2012-06-25 21:53:49.556446369 +0100
> @@ -28,6 +28,7 @@
>  import grub.ExtLinuxConf
>  
>  PYGRUB_VER = 0.6
> +fs_read_max=1048576

All other constants in the global scope are in all caps. "1024 * 1024"
is a bit more readable.

>  def enable_cursor(ison):
>      if ison:
> @@ -448,7 +449,8 @@
>          if self.__dict__.get('cf', None) is None:
>              raise RuntimeError, "couldn't find bootloader config file in the image provided."
>          f = fs.open_file(self.cf.filename)
> -        buf = f.read()
> +        # limit read size to avoid pathological cases
> +        buf = f.read(fs_read_max)
>          del f
>          self.cf.parse(buf)
>  
> @@ -697,6 +699,39 @@
>      def usage():
>          print >> sys.stderr, "Usage: %s [-q|--quiet] [-i|--interactive] [-n|--not-really] [--output=] [--kernel=] [--ramdisk=] [--args=] [--entry=] [--output-directory=] [--output-format=sxp|simple|simple0] <image>" %(sys.argv[0],)
>  
> +    def copy_from_image(fs, file_to_read, file_type, output_directory,
> +                                              not_really, clean_extra_file):

Could the indention here follow PEP-8 [1] guidelines?

> +        if not_really:
> +            if fs.file_exists(file_to_read):
> +                return "<%s:%s>" % (file_type,file_to_read)

missing space after ,

> +            else:
> +                sys.exit("The requested %s file does not exist" % file_type)
> +        try:
> +            datafile = fs.open_file(file_to_read)
> +        except:

I personally don't like the pattern of:
    try:
        ...
    except:
        ...
There's a lot of opportunity to hide exceptions other than those that
you'd expect. At minimum, I'd capture the exception and try to add it
to the error message.

> +            if clean_extra_file:
> +                os.unlink(clean_extra_file)

It would seem that you're pushing a cleanup task to the innermost
function. Shouldn't it be the responsibility of the caller to clean up
on an exception?

> +            sys.exit("Error opening %s" % file_to_read)
> +        (tfd, ret) = tempfile.mkstemp(prefix="boot_"+file_type+".",
> +                                                       dir=output_directory)

Fix indention to be PEP-8.

> +        dataoff=0
> +        while True:
> +            data=datafile.read(fs_read_max,dataoff)

Missing space after ,
Missing spaces before and after =

> +            if len(data) == 0:
> +                os.close(tfd)
> +                del datafile
> +                return ret
> +            try:
> +                os.write(tfd, data)
> +            except:

try: ... except: again can make us blind to unexpected errors. At
minimum capture the error and include it in the exit string.

> +                os.close(tfd)
> +                os.unlink(ret)
> +                del datafile
> +                if clean_extra_file:
> +                    os.unlink(clean_extra_file)
> +                sys.exit("error writing temporary copy of "+file_type)
> +            dataoff+=len(data)

Spaces before and after +=

> +
>      try:
>          opts, args = getopt.gnu_getopt(sys.argv[1:], 'qinh::',
>                                     ["quiet", "interactive", "not-really", "help", 
> @@ -821,24 +856,12 @@
>      if not fs:
>          raise RuntimeError, "Unable to find partition containing kernel"
>  
> -    if not_really:
> -        bootcfg["kernel"] = "<kernel:%s>" % chosencfg["kernel"]
> -    else:
> -        data = fs.open_file(chosencfg["kernel"]).read()
> -        (tfd, bootcfg["kernel"]) = tempfile.mkstemp(prefix="boot_kernel.",
> -                                                    dir=output_directory)
> -        os.write(tfd, data)
> -        os.close(tfd)
> +    bootcfg["kernel"] = copy_from_image(fs, chosencfg["kernel"], 
> +                              "kernel", output_directory, not_really, "")

PEP-8 indention

>  
>      if chosencfg["ramdisk"]:
> -        if not_really:
> -            bootcfg["ramdisk"] = "<ramdisk:%s>" % chosencfg["ramdisk"]
> -        else:
> -            data = fs.open_file(chosencfg["ramdisk"],).read()
> -            (tfd, bootcfg["ramdisk"]) = tempfile.mkstemp(
> -                prefix="boot_ramdisk.", dir=output_directory)
> -            os.write(tfd, data)
> -            os.close(tfd)
> +        bootcfg["ramdisk"] = copy_from_image(fs, chosencfg["ramdisk"],
> +              "ramdisk", output_directory, not_really, bootcfg["kernel"])

PEP-8 indention. This seems to be the place that should be cleaning up
images on error. E.g.:

    try:
        bootcfg["ramdisk"] = copy_from_image(fs, chosencfg["ramdisk"],
                                             "ramdisk", output_directory,
                                             not_really)
    except Exception, e:
        exc_info = sys.exc_info()
        try:
	    os.unlink(bootcfg["kernel"])
        except Exception, e:
	    # log an error
        # re-raise original exception
        raise exc_info[0], exc_info[1], exc_into[2]


Re-raising the exception is the fancy thing to do. If we don't care
if os.unlink() raises an exception, you could leave off the inner
try: and just use "raise" to re-raise.

>      else:
>          initrd = None
>  

Matt

[1] http://www.python.org/dev/peps/pep-0008/#indentation

  reply	other threads:[~2012-06-26  0:13 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-06-22 18:37 pygrub: verify chosen kernel really exists Andrew Cooper
2012-06-25  9:07 ` Ian Campbell
2012-06-25 10:17   ` M A Young
2012-06-25 10:52     ` Ian Campbell
2012-06-25 11:04       ` M A Young
2012-06-25 21:34       ` pygrub: avoid problems if guest files are large etc M A Young
2012-06-26  0:13         ` Matt Wilson [this message]
2012-07-01 23:47           ` M A Young
2012-07-02 11:22             ` Ian Campbell
2012-07-02 19:42               ` Matt Wilson
2012-07-03  8:09                 ` Ian Campbell
2012-07-03 16:07                   ` Matt Wilson
2012-07-04 14:48             ` Ian Campbell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120626001321.GC8088@US-SEA-R8XVZTX \
    --to=msw@amazon.com \
    --cc=Andrew.Cooper3@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=m.a.young@durham.ac.uk \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.