Example #1
0
func (s *imageURLSuite) TestImageDownloadURLUnsupportedContainer(c *gc.C) {
	_, err := container.ImageDownloadURL(instance.KVM, "trusty", "amd64", "released", "")
	c.Assert(err, gc.ErrorMatches, "unsupported container .*")
}
Example #2
0
// fetchAndCacheLxcImage fetches an lxc image tarball from http://cloud-images.ubuntu.com
// and caches it in the state blobstore.
func (h *imagesDownloadHandler) fetchAndCacheLxcImage(storage imagestorage.Storage, envuuid, series, arch string) error {
	cfg, err := h.state.EnvironConfig()
	if err != nil {
		return errors.Trace(err)
	}
	imageURL, err := container.ImageDownloadURL(instance.LXC, series, arch, cfg.CloudImageBaseURL())
	if err != nil {
		return errors.Annotatef(err, "cannot determine LXC image URL: %v", err)
	}

	// Fetch the image checksum.
	imageFilename := path.Base(imageURL)
	shafile := strings.Replace(imageURL, imageFilename, "SHA256SUMS", -1)
	shaResp, err := http.Get(shafile)
	if err != nil {
		return errors.Annotatef(err, "cannot get sha256 data from %v", shafile)
	}
	defer shaResp.Body.Close()
	shaInfo, err := ioutil.ReadAll(shaResp.Body)
	if err != nil {
		return errors.Annotatef(err, "cannot read sha256 data from %v", shafile)
	}

	// The sha file has lines like:
	// "<checksum> *<imageFilename>"
	checksum := ""
	for _, line := range strings.Split(string(shaInfo), "\n") {
		parts := strings.Split(line, "*")
		if len(parts) != 2 {
			continue
		}
		if parts[1] == imageFilename {
			checksum = strings.TrimSpace(parts[0])
			break
		}
	}
	if checksum == "" {
		return errors.Errorf("cannot find sha256 checksum for %v", imageFilename)
	}

	// Fetch the image.
	logger.Debugf("fetching LXC image from: %v", imageURL)
	resp, err := http.Get(imageURL)
	if err != nil {
		return errors.Annotatef(err, "cannot get image from %v", imageURL)
	}
	logger.Debugf("lxc image has size: %v bytes", resp.ContentLength)
	defer resp.Body.Close()

	hash := sha256.New()
	// Set up a chain of readers to pull in the data and calculate the checksum.
	rdr := io.TeeReader(resp.Body, hash)

	metadata := &imagestorage.Metadata{
		EnvUUID:   envuuid,
		Kind:      string(instance.LXC),
		Series:    series,
		Arch:      arch,
		Size:      resp.ContentLength,
		SHA256:    checksum,
		SourceURL: imageURL,
	}

	// Stream the image to storage.
	err = networkOperationWitDefaultRetries(func() error {
		return storage.AddImage(rdr, metadata)
	}, "add os image to blobstore")()
	if err != nil {
		return errors.Trace(err)
	}
	// Better check the downloaded image checksum.
	downloadChecksum := fmt.Sprintf("%x", hash.Sum(nil))
	if downloadChecksum != checksum {
		err := networkOperationWitDefaultRetries(func() error {
			return storage.DeleteImage(metadata)
		}, "delete os image from blobstore")()
		if err != nil {
			logger.Errorf("checksum mismatch, failed to delete image from storage: %v", err)
		}
		return errors.Errorf("download checksum mismatch %s != %s", downloadChecksum, checksum)
	}
	return nil
}
Example #3
0
func (s *imageURLSuite) TestImageDownloadURLOtherBase(c *gc.C) {
	imageDownloadURL, err := container.ImageDownloadURL(instance.LXC, "trusty", "amd64", "released", "other://cloud-images")
	c.Assert(err, gc.IsNil)
	c.Assert(imageDownloadURL, gc.Equals, "other://cloud-images/trusty-released-amd64-root.tar.gz")
}