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