github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/version/ubuntu/supportedseries.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package ubuntu 5 6 import ( 7 "bufio" 8 "fmt" 9 "io" 10 "os" 11 "strings" 12 "sync" 13 14 "github.com/juju/loggo" 15 ) 16 17 var logger = loggo.GetLogger("juju.ubuntu") 18 19 // seriesVersions provides a mapping between Ubuntu series names and version numbers. 20 // The values here are current as of the time of writing. On Ubuntu systems, we update 21 // these values from /usr/share/distro-info/ubuntu.csv to ensure we have the latest values. 22 // On non-Ubuntu systems, these values provide a nice fallback option. 23 // Exported so tests can change the values to ensure the distro-info lookup works. 24 var seriesVersions = map[string]string{ 25 "precise": "12.04", 26 "quantal": "12.10", 27 "raring": "13.04", 28 "saucy": "13.10", 29 "trusty": "14.04", 30 "utopic": "14.10", 31 } 32 33 var ( 34 seriesVersionsMutex sync.Mutex 35 updatedseriesVersions bool 36 ) 37 38 // SeriesVersion returns the version number for the specified Ubuntu series. 39 func SeriesVersion(series string) (string, error) { 40 if series == "" { 41 panic("cannot pass empty series to SeriesVersion()") 42 } 43 seriesVersionsMutex.Lock() 44 defer seriesVersionsMutex.Unlock() 45 if vers, ok := seriesVersions[series]; ok { 46 return vers, nil 47 } 48 updateSeriesVersions() 49 if vers, ok := seriesVersions[series]; ok { 50 return vers, nil 51 } 52 return "", fmt.Errorf("invalid series %q", series) 53 } 54 55 // SupportedSeries returns the Ubuntu series on which we can run Juju workloads. 56 func SupportedSeries() []string { 57 seriesVersionsMutex.Lock() 58 defer seriesVersionsMutex.Unlock() 59 updateSeriesVersions() 60 var series []string 61 for s := range seriesVersions { 62 series = append(series, s) 63 } 64 return series 65 } 66 67 func updateSeriesVersions() { 68 if !updatedseriesVersions { 69 err := updateDistroInfo() 70 if err != nil { 71 logger.Warningf("failed to update distro info: %v", err) 72 } 73 updatedseriesVersions = true 74 } 75 } 76 77 // updateDistroInfo updates seriesVersions from /usr/share/distro-info/ubuntu.csv if possible.. 78 func updateDistroInfo() error { 79 // We need to find the series version eg 12.04 from the series eg precise. Use the information found in 80 // /usr/share/distro-info/ubuntu.csv provided by distro-info-data package. 81 f, err := os.Open("/usr/share/distro-info/ubuntu.csv") 82 if err != nil { 83 // On non-Ubuntu systems this file won't exist but that's expected. 84 return nil 85 } 86 defer f.Close() 87 bufRdr := bufio.NewReader(f) 88 // Only find info for precise or later. 89 preciseOrLaterFound := false 90 for { 91 line, err := bufRdr.ReadString('\n') 92 if err == io.EOF { 93 break 94 } 95 if err != nil { 96 return fmt.Errorf("reading distro info file file: %v", err) 97 } 98 // lines are of the form: "12.04 LTS,Precise Pangolin,precise,2011-10-13,2012-04-26,2017-04-26" 99 parts := strings.Split(line, ",") 100 // Ignore any malformed lines. 101 if len(parts) < 3 { 102 continue 103 } 104 series := parts[2] 105 if series == "precise" { 106 preciseOrLaterFound = true 107 } 108 if series != "precise" && !preciseOrLaterFound { 109 continue 110 } 111 // the numeric version may contain a LTS moniker so strip that out. 112 seriesInfo := strings.Split(parts[0], " ") 113 seriesVersions[series] = seriesInfo[0] 114 } 115 return nil 116 }