[FFE] Image Store Proxy must handle compressed images

Bug #445714 reported by Gustavo Niemeyer
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
image-store-proxy (Ubuntu)
Fix Released
Undecided
Mathias Gug

Bug Description

Up to version 1.0.1, the image store proxy cannot handle compressed images, which means Canonical would have to provide 10GB files uncompressed somewhere, rather than the much smaller 700MB versions. Version 1.0.2 is able to handle gzip compressed images.

It's important to integrate this change in time for Karmic, otherwise even if we implement support for compressed images in Lucid, we'd still have to provide the uncompressed images for Karmic-based deployments to work.

The change has been properly unittested, and manually tested as well with a real installation of a compressed image and of an uncompressed image to ensure it continues working correctly.

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

The relevant code change between 1.0.1 and 1.0.2 is attached. The rest of the diff is documentation and tests.

Changed in ubuntu:
assignee: nobody → Mathias Gug (mathiaz)
Mathias Gug (mathiaz)
affects: ubuntu → image-store-proxy (Ubuntu)
Revision history for this message
Mathias Gug (mathiaz) wrote :

I've attached the complete debdiff.

Revision history for this message
Martin Pitt (pitti) wrote :

Can the user or third party ever control the file name argument? Things like

  + status, output = commands.getstatusoutput("gunzip %s" % localPath)

are never robust, since localPath could contain spaces, or worse, semicolons and other shell commands. That's why Python has an excellent subprocess module, which avoids intermediate shells, and still makes it comfortable to capture status and stdout/err.

Revision history for this message
Martin Pitt (pitti) wrote :

The new feature is fine, it's small enough. Howver, I'd appreciate if the gunzip calling could be cleaned up, such as

  gunzip = subprocess.Popen(['gunzip', localPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  (output, output_err) = gunzip.communicate()
  status = gunzip.returncode

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

No, this is not a security issue. localPath is based on the sha256, which is checked right above for validity.

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Scott Moser pointed out that he wants to use .tar.gz on the published images, because using the --sparse option of tar greatly reduces the size of the resulting file in comparison to plain gzip, so I went ahead and added support for .tar.gz on the image store proxy too, in addition to .gz.

This is all in release 1.0.3:

http://launchpad.net/image-store-proxy/1.0/1.0.3/+download/image-store-proxy-1.0.3.tar.gz

I've also added some logic to check that the hash used in the filename is indeed a hash, just for being pedantic. In practice, the image data must be signed by Canonical itself before getting to this point, so it should be safe no matter what.

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Oh, again, this was all unittested, and manually tested using the fake store api.

Revision history for this message
Mathias Gug (mathiaz) wrote :

I've added the complete debdiff.

Revision history for this message
Martin Pitt (pitti) wrote :

So, I rely on your word that this will only ever see save file names. However, I really advise you to stop using shells and strings for running commands from programs. It's bad style, involves useless shells, is a potential source of bugs and security holes, and is not even less effort than doing it properly.

Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package image-store-proxy - 1.0.3-0ubuntu1

---------------
image-store-proxy (1.0.3-0ubuntu1) karmic; urgency=low

  * New upstream release (LP: #445714):
    - support gzip and tar+gz compressed images.
  * Fix restart init action to use STARTTIME only if it's set.

 -- Mathias Gug <email address hidden> Thu, 08 Oct 2009 22:31:34 -0400

Changed in image-store-proxy (Ubuntu):
status: New → Fix Released
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Martin,

Please rest assured I understand very well all of the consequences of using one approach or the other, and opt to use one or the other depending on specific needs. In fact, if you look through the code you'll see that in some cases subprocess was used.

In the case at hand I could very well have avoided it, but the fact that:

 1) it was safe;
 2) it was a one liner;
 3) It is rarely executed; and
 4) I had very little time to implement the system

Guided me towards using this approach.

Also note that it's easy for people to get Subprocess wrong. We should probably implement a wrapper which implements the equivalent of "getstatusoutput()" in a safe way.

In your example above, you actually got it pretty much right. One detail I'd change on it is that you pipe the error output and the standard output into different file descriptors. This means that if the command run outputs error messages interleaved with normal output, the normal output and the error output will be disjoint, and so will be hard to interpret in a log or in the stdout. The proper way would be to use the option stderr=subprocess.STDOUT, so that the error can be observed at the correct places.

Either way, I agree with you, it's a good practice to use subprocess. Let's have more of it.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.