func parseMetadataFromParams(p params.CloudImageMetadata) cloudimagemetadata.Metadata { parseSource := func(s string) cloudimagemetadata.SourceType { switch cloudimagemetadata.SourceType(strings.ToLower(s)) { case cloudimagemetadata.Public: return cloudimagemetadata.Public case cloudimagemetadata.Custom: return cloudimagemetadata.Custom default: panic(fmt.Sprintf("unknown cloud image metadata source %q", s)) } } result := cloudimagemetadata.Metadata{ cloudimagemetadata.MetadataAttributes{ Stream: p.Stream, Region: p.Region, Series: p.Series, Arch: p.Arch, VirtualType: p.VirtualType, RootStorageType: p.RootStorageType, RootStorageSize: p.RootStorageSize, Source: parseSource(p.Source), }, p.ImageId, } if p.Stream == "" { result.Stream = "released" } return result }
func (s *cloudImageMetadataSuite) TestSaveDiffMetadataConcurrentlyAndOrderByDateCreated(c *gc.C) { attrs := cloudimagemetadata.MetadataAttributes{ Stream: "stream", Series: "series", Arch: "arch", } metadata0 := cloudimagemetadata.Metadata{attrs, "0"} metadata1 := cloudimagemetadata.Metadata{attrs, "1"} metadata1.Stream = "scream" s.assertConcurrentSave(c, metadata0, // add this one metadata1, // add this one // last added should be first as order is by date created metadata1, // verify it's in the list metadata0, // verify it's in the list ) }
func (api *API) parseMetadataFromParams(p params.CloudImageMetadata, env environs.Environ) (cloudimagemetadata.Metadata, error) { result := cloudimagemetadata.Metadata{ cloudimagemetadata.MetadataAttributes{ Stream: p.Stream, Region: p.Region, Version: p.Version, Series: p.Series, Arch: p.Arch, VirtType: p.VirtType, RootStorageType: p.RootStorageType, RootStorageSize: p.RootStorageSize, Source: p.Source, }, p.Priority, p.ImageId, } // Fill in any required default values. if p.Stream == "" { result.Stream = env.Config().ImageStream() } if p.Source == "" { result.Source = "custom" } if result.Arch == "" { result.Arch = "amd64" } if result.Series == "" { result.Series = config.PreferredSeries(env.Config()) } if result.Region == "" { // If the env supports regions, use the env default. if r, ok := env.(simplestreams.HasRegion); ok { spec, err := r.Region() if err != nil { return cloudimagemetadata.Metadata{}, errors.Annotatef(err, "getting cloud region") } result.Region = spec.Region } } return result, nil }
// storeImageMetadataInState writes image metadata into state store. func storeImageMetadataInState(st *state.State, env environs.Environ, source string, priority int, existingMetadata []*imagemetadata.ImageMetadata) error { if len(existingMetadata) == 0 { return nil } cfg := env.Config() metadataState := make([]cloudimagemetadata.Metadata, len(existingMetadata)) for i, one := range existingMetadata { m := cloudimagemetadata.Metadata{ MetadataAttributes: cloudimagemetadata.MetadataAttributes{ Stream: one.Stream, Region: one.RegionName, Arch: one.Arch, VirtType: one.VirtType, RootStorageType: one.Storage, Source: source, Version: one.Version, }, Priority: priority, ImageId: one.Id, } s, err := seriesFromVersion(one.Version) if err != nil { return errors.Annotatef(err, "cannot determine series for version %v", one.Version) } m.Series = s if m.Stream == "" { m.Stream = cfg.ImageStream() } if m.Source == "" { m.Source = "custom" } metadataState[i] = m } if err := st.CloudImageMetadataStorage.SaveMetadata(metadataState); err != nil { return errors.Annotatef(err, "cannot cache image metadata") } return nil }
// imageMetadataFromDataSources finds image metadata that match specified criteria in existing data sources. func (p *ProvisionerAPI) imageMetadataFromDataSources(env environs.Environ, constraint *imagemetadata.ImageConstraint) ([]params.CloudImageMetadata, error) { sources, err := environs.ImageMetadataSources(env) if err != nil { return nil, errors.Trace(err) } cfg := env.Config() toModel := func(m *imagemetadata.ImageMetadata, mSeries string, source string, priority int) cloudimagemetadata.Metadata { result := cloudimagemetadata.Metadata{ MetadataAttributes: cloudimagemetadata.MetadataAttributes{ Region: m.RegionName, Arch: m.Arch, VirtType: m.VirtType, RootStorageType: m.Storage, Source: source, Series: mSeries, Stream: m.Stream, Version: m.Version, }, Priority: priority, ImageId: m.Id, } // TODO (anastasiamac 2016-08-24) This is a band-aid solution. // Once correct value is read from simplestreams, this needs to go. // Bug# 1616295 if result.Stream == "" { result.Stream = constraint.Stream } if result.Stream == "" { result.Stream = cfg.ImageStream() } return result } var metadataState []cloudimagemetadata.Metadata for _, source := range sources { logger.Debugf("looking in data source %v", source.Description()) found, info, err := imagemetadata.Fetch([]simplestreams.DataSource{source}, constraint) if err != nil { // Do not stop looking in other data sources if there is an issue here. logger.Warningf("encountered %v while getting published images metadata from %v", err, source.Description()) continue } for _, m := range found { mSeries, err := series.VersionSeries(m.Version) if err != nil { logger.Warningf("could not determine series for image id %s: %v", m.Id, err) continue } metadataState = append(metadataState, toModel(m, mSeries, info.Source, source.Priority())) } } if len(metadataState) > 0 { if err := p.st.CloudImageMetadataStorage.SaveMetadata(metadataState); err != nil { // No need to react here, just take note logger.Warningf("failed to save published image metadata: %v", err) } } // Since we've fallen through to data sources search and have saved all needed images into controller, // let's try to get them from controller to avoid duplication of conversion logic here. all, err := p.imageMetadataFromState(constraint) if err != nil { return nil, errors.Annotate(err, "could not read metadata from controller after saving it there from data sources") } if len(all) == 0 { return nil, errors.NotFoundf("image metadata for series %v, arch %v", constraint.Series, constraint.Arches) } return all, nil }