// processGet handles a tools GET request. func (h *toolsDownloadHandler) processGet(r *http.Request, st *state.State) ([]byte, error) { version, err := version.ParseBinary(r.URL.Query().Get(":version")) if err != nil { return nil, errors.Annotate(err, "error parsing version") } storage, err := st.ToolsStorage() if err != nil { return nil, errors.Annotate(err, "error getting tools storage") } defer storage.Close() _, reader, err := storage.Open(version.String()) if errors.IsNotFound(err) { // Tools could not be found in tools storage, // so look for them in simplestreams, fetch // them and cache in tools storage. logger.Infof("%v tools not found locally, fetching", version) reader, err = h.fetchAndCacheTools(version, storage, st) if err != nil { err = errors.Annotate(err, "error fetching tools") } } if err != nil { return nil, err } defer reader.Close() data, err := ioutil.ReadAll(reader) if err != nil { return nil, errors.Annotate(err, "failed to read tools tarball") } return data, nil }
// populateTools stores uploaded tools in provider storage // and updates the tools metadata. func (c *BootstrapCommand) populateTools(st *state.State, env environs.Environ) error { agentConfig := c.CurrentConfig() dataDir := agentConfig.DataDir() current := version.Binary{ Number: jujuversion.Current, Arch: arch.HostArch(), Series: series.HostSeries(), } tools, err := agenttools.ReadTools(dataDir, current) if err != nil { return errors.Trace(err) } data, err := ioutil.ReadFile(filepath.Join( agenttools.SharedToolsDir(dataDir, current), "tools.tar.gz", )) if err != nil { return errors.Trace(err) } toolstorage, err := st.ToolsStorage() if err != nil { return errors.Trace(err) } defer toolstorage.Close() var toolsVersions []version.Binary if strings.HasPrefix(tools.URL, "file://") { // Tools were uploaded: clone for each series of the same OS. os, err := series.GetOSFromSeries(tools.Version.Series) if err != nil { return errors.Trace(err) } osSeries := series.OSSupportedSeries(os) for _, series := range osSeries { toolsVersion := tools.Version toolsVersion.Series = series toolsVersions = append(toolsVersions, toolsVersion) } } else { // Tools were downloaded from an external source: don't clone. toolsVersions = []version.Binary{tools.Version} } for _, toolsVersion := range toolsVersions { metadata := binarystorage.Metadata{ Version: toolsVersion.String(), Size: tools.Size, SHA256: tools.SHA256, } logger.Debugf("Adding tools: %v", toolsVersion) if err := toolstorage.Add(bytes.NewReader(data), metadata); err != nil { return errors.Trace(err) } } return nil }
func (s *toolsSuite) getToolsMetadataFromStorage(c *gc.C, st *state.State) []binarystorage.Metadata { storage, err := st.ToolsStorage() c.Assert(err, jc.ErrorIsNil) defer storage.Close() metadata, err := storage.AllMetadata() c.Assert(err, jc.ErrorIsNil) return metadata }
func (s *toolsSuite) getToolsFromStorage(c *gc.C, st *state.State, vers string) (binarystorage.Metadata, []byte) { storage, err := st.ToolsStorage() c.Assert(err, jc.ErrorIsNil) defer storage.Close() metadata, r, err := storage.Open(vers) c.Assert(err, jc.ErrorIsNil) data, err := ioutil.ReadAll(r) r.Close() c.Assert(err, jc.ErrorIsNil) return metadata, data }
func (s *toolsSuite) storeFakeTools(c *gc.C, st *state.State, content string, metadata binarystorage.Metadata) *coretools.Tools { storage, err := st.ToolsStorage() c.Assert(err, jc.ErrorIsNil) defer storage.Close() err = storage.Add(strings.NewReader(content), metadata) c.Assert(err, jc.ErrorIsNil) return &coretools.Tools{ Version: version.MustParseBinary(metadata.Version), Size: metadata.Size, SHA256: metadata.SHA256, } }
// handleUpload uploads the tools data from the reader to env storage as the specified version. func (h *toolsUploadHandler) handleUpload(r io.Reader, toolsVersions []version.Binary, serverRoot string, st *state.State) (*tools.Tools, error) { // Check if changes are allowed and the command may proceed. blockChecker := common.NewBlockChecker(st) if err := blockChecker.ChangeAllowed(); err != nil { return nil, errors.Trace(err) } storage, err := st.ToolsStorage() if err != nil { return nil, err } defer storage.Close() // Read the tools tarball from the request, calculating the sha256 along the way. data, sha256, err := readAndHash(r) if err != nil { return nil, err } if len(data) == 0 { return nil, errors.BadRequestf("no tools uploaded") } // TODO(wallyworld): check integrity of tools tarball. // Store tools and metadata in tools storage. for _, v := range toolsVersions { metadata := binarystorage.Metadata{ Version: v.String(), Size: int64(len(data)), SHA256: sha256, } logger.Debugf("uploading tools %+v to storage", metadata) if err := storage.Add(bytes.NewReader(data), metadata); err != nil { return nil, err } } tools := &tools.Tools{ Version: toolsVersions[0], Size: int64(len(data)), SHA256: sha256, URL: common.ToolsURL(serverRoot, toolsVersions[0]), } return tools, nil }