// loadImage loads an os image from the blobstore, // downloading and caching it if necessary. func (h *imagesDownloadHandler) loadImage(st *state.State, envuuid, kind, series, arch string) ( *imagestorage.Metadata, io.ReadCloser, error, ) { // We want to ensure that if an image needs to be downloaded and cached, // this only happens once. imageIdent := fmt.Sprintf("image-%s-%s-%s-%s", envuuid, kind, series, arch) lockDir := filepath.Join(h.dataDir, "locks") lock, err := fslock.NewLock(lockDir, imageIdent, fslock.Defaults()) if err != nil { return nil, nil, errors.Trace(err) } lock.Lock("fetch and cache image " + imageIdent) defer lock.Unlock() storage := st.ImageStorage() metadata, imageReader, err := storage.Image(kind, series, arch) // Not in storage, so go fetch it. if errors.IsNotFound(err) { if err := h.fetchAndCacheLxcImage(storage, envuuid, series, arch); err != nil { return nil, nil, errors.Annotate(err, "error fetching and caching image") } err = networkOperationWitDefaultRetries(func() error { metadata, imageReader, err = storage.Image(string(instance.LXC), series, arch) return err }, "streaming os image from blobstore")() } if err != nil { return nil, nil, errors.Trace(err) } return metadata, imageReader, nil }
func (s *imageSuite) getImageFromStorage(c *gc.C, st *state.State, kind, series, arch string) (*imagestorage.Metadata, []byte) { storage := st.ImageStorage() metadata, r, err := storage.Image(kind, series, arch) c.Assert(err, gc.IsNil) data, err := ioutil.ReadAll(r) r.Close() c.Assert(err, gc.IsNil) return metadata, data }
func (s *imageSuite) storeFakeImage(c *gc.C, st *state.State, kind, series, arch string) { storage := st.ImageStorage() metadata := &imagestorage.Metadata{ ModelUUID: st.ModelUUID(), Kind: kind, Series: series, Arch: arch, Size: int64(len(testImageData)), SHA256: testImageChecksum, SourceURL: "http://path", } err := storage.AddImage(strings.NewReader(testImageData), metadata) c.Assert(err, gc.IsNil) }