func (s *imageURLSuite) TestImageDownloadURLUnsupportedContainer(c *gc.C) { _, err := container.ImageDownloadURL(instance.KVM, "trusty", "amd64", "released", "") c.Assert(err, gc.ErrorMatches, "unsupported container .*") }
// 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 }
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") }