github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/version/osversion.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package version
     5  
     6  import (
     7  	"fmt"
     8  	"io/ioutil"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/juju/errors"
    13  	"github.com/juju/loggo"
    14  )
    15  
    16  var logger = loggo.GetLogger("juju.version")
    17  
    18  // mustOSVersion will panic if the osVersion is "unknown" due
    19  // to an error.
    20  //
    21  // If you want to avoid the panic, call osVersion and handle
    22  // the error.
    23  func mustOSVersion() string {
    24  	version, err := osVersion()
    25  	if err != nil {
    26  		panic("osVersion reported an error: " + err.Error())
    27  	}
    28  	return version
    29  }
    30  
    31  // MustOSFromSeries will panic if the series represents an "unknown"
    32  // operating system
    33  func MustOSFromSeries(series string) OSType {
    34  	operatingSystem, err := GetOSFromSeries(series)
    35  	if err != nil {
    36  		panic("osVersion reported an error: " + err.Error())
    37  	}
    38  	return operatingSystem
    39  }
    40  
    41  func readOSRelease() (map[string]string, error) {
    42  	values := map[string]string{}
    43  
    44  	contents, err := ioutil.ReadFile(osReleaseFile)
    45  	if err != nil {
    46  		return values, err
    47  	}
    48  	releaseDetails := strings.Split(string(contents), "\n")
    49  	for _, val := range releaseDetails {
    50  		c := strings.SplitN(val, "=", 2)
    51  		if len(c) != 2 {
    52  			continue
    53  		}
    54  		values[c[0]] = strings.Trim(c[1], "\t '\"")
    55  	}
    56  	_, ok := values["ID"]
    57  	if !ok {
    58  		return values, errors.New("OS release file is missing ID")
    59  	}
    60  	_, ok = values["VERSION_ID"]
    61  	if !ok {
    62  		return values, errors.New("OS release file is missing VERSION_ID")
    63  	}
    64  	return values, nil
    65  }
    66  
    67  func getValue(from map[string]string, val string) (string, error) {
    68  	for serie, ver := range from {
    69  		if ver == val {
    70  			return serie, nil
    71  		}
    72  	}
    73  	return "unknown", errors.New("Could not determine series")
    74  }
    75  
    76  func readSeries() (string, error) {
    77  	values, err := readOSRelease()
    78  	if err != nil {
    79  		return "unknown", err
    80  	}
    81  	updateSeriesVersions()
    82  	switch values["ID"] {
    83  	case strings.ToLower(Ubuntu.String()):
    84  		return getValue(ubuntuSeries, values["VERSION_ID"])
    85  	case strings.ToLower(CentOS.String()):
    86  		codename := fmt.Sprintf("%s%s", values["ID"], values["VERSION_ID"])
    87  		return getValue(centosSeries, codename)
    88  	default:
    89  		return "unknown", nil
    90  	}
    91  }
    92  
    93  // kernelToMajor takes a dotted version and returns just the Major portion
    94  func kernelToMajor(getKernelVersion func() (string, error)) (int, error) {
    95  	fullVersion, err := getKernelVersion()
    96  	if err != nil {
    97  		return 0, err
    98  	}
    99  	parts := strings.SplitN(fullVersion, ".", 2)
   100  	majorVersion, err := strconv.ParseInt(parts[0], 10, 32)
   101  	if err != nil {
   102  		return 0, err
   103  	}
   104  	return int(majorVersion), nil
   105  }
   106  
   107  func macOSXSeriesFromKernelVersion(getKernelVersion func() (string, error)) (string, error) {
   108  	majorVersion, err := kernelToMajor(getKernelVersion)
   109  	if err != nil {
   110  		logger.Infof("unable to determine OS version: %v", err)
   111  		return "unknown", err
   112  	}
   113  	return macOSXSeriesFromMajorVersion(majorVersion)
   114  }
   115  
   116  // TODO(jam): 2014-05-06 https://launchpad.net/bugs/1316593
   117  // we should have a system file that we can read so this can be updated without
   118  // recompiling Juju. For now, this is a lot easier, and also solves the fact
   119  // that we want to populate version.Current.Series during init() time, before
   120  // we've potentially read that information from anywhere else
   121  // macOSXSeries maps from the Darwin Kernel Major Version to the Mac OSX
   122  // series.
   123  var macOSXSeries = map[int]string{
   124  	14: "yosemite",
   125  	13: "mavericks",
   126  	12: "mountainlion",
   127  	11: "lion",
   128  	10: "snowleopard",
   129  	9:  "leopard",
   130  	8:  "tiger",
   131  	7:  "panther",
   132  	6:  "jaguar",
   133  	5:  "puma",
   134  }
   135  
   136  func macOSXSeriesFromMajorVersion(majorVersion int) (string, error) {
   137  	series, ok := macOSXSeries[majorVersion]
   138  	if !ok {
   139  		return "unknown", errors.Errorf("unknown series %q", series)
   140  	}
   141  	return series, nil
   142  }