...

Source file src/github.com/shirou/gopsutil/host/host_solaris.go

Documentation: github.com/shirou/gopsutil/host

     1  package host
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"context"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"regexp"
    12  	"strconv"
    13  	"strings"
    14  
    15  	"github.com/shirou/gopsutil/internal/common"
    16  )
    17  
    18  func HostIDWithContext(ctx context.Context) (string, error) {
    19  	platform, err := parseReleaseFile()
    20  	if err != nil {
    21  		return "", err
    22  	}
    23  
    24  	if platform == "SmartOS" {
    25  		// If everything works, use the current zone ID as the HostID if present.
    26  		zonename, err := exec.LookPath("zonename")
    27  		if err == nil {
    28  			out, err := invoke.CommandWithContext(ctx, zonename)
    29  			if err == nil {
    30  				sc := bufio.NewScanner(bytes.NewReader(out))
    31  				for sc.Scan() {
    32  					line := sc.Text()
    33  
    34  					// If we're in the global zone, rely on the hostname.
    35  					if line == "global" {
    36  						hostname, err := os.Hostname()
    37  						if err == nil {
    38  							return hostname, nil
    39  						}
    40  					} else {
    41  						return strings.TrimSpace(line), nil
    42  					}
    43  				}
    44  			}
    45  		}
    46  	}
    47  
    48  	// If HostID is still unknown, use hostid(1), which can lie to callers but at
    49  	// this point there are no hardware facilities available.  This behavior
    50  	// matches that of other supported OSes.
    51  	hostID, err := exec.LookPath("hostid")
    52  	if err == nil {
    53  		out, err := invoke.CommandWithContext(ctx, hostID)
    54  		if err == nil {
    55  			sc := bufio.NewScanner(bytes.NewReader(out))
    56  			for sc.Scan() {
    57  				line := sc.Text()
    58  				return strings.TrimSpace(line), nil
    59  			}
    60  		}
    61  	}
    62  
    63  	return "", nil
    64  }
    65  
    66  // Count number of processes based on the number of entries in /proc
    67  func numProcs(ctx context.Context) (uint64, error) {
    68  	dirs, err := ioutil.ReadDir("/proc")
    69  	if err != nil {
    70  		return 0, err
    71  	}
    72  	return uint64(len(dirs)), nil
    73  }
    74  
    75  var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
    76  
    77  func BootTimeWithContext(ctx context.Context) (uint64, error) {
    78  	kstat, err := exec.LookPath("kstat")
    79  	if err != nil {
    80  		return 0, err
    81  	}
    82  
    83  	out, err := invoke.CommandWithContext(ctx, kstat, "-p", "unix:0:system_misc:boot_time")
    84  	if err != nil {
    85  		return 0, err
    86  	}
    87  
    88  	kstats := kstatMatch.FindAllStringSubmatch(string(out), -1)
    89  	if len(kstats) != 1 {
    90  		return 0, fmt.Errorf("expected 1 kstat, found %d", len(kstats))
    91  	}
    92  
    93  	return strconv.ParseUint(kstats[0][2], 10, 64)
    94  }
    95  
    96  func UptimeWithContext(ctx context.Context) (uint64, error) {
    97  	bootTime, err := BootTime()
    98  	if err != nil {
    99  		return 0, err
   100  	}
   101  	return timeSince(bootTime), nil
   102  }
   103  
   104  func UsersWithContext(ctx context.Context) ([]UserStat, error) {
   105  	return []UserStat{}, common.ErrNotImplementedError
   106  }
   107  
   108  func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
   109  	return []TemperatureStat{}, common.ErrNotImplementedError
   110  }
   111  
   112  func VirtualizationWithContext(ctx context.Context) (string, string, error) {
   113  	return "", "", common.ErrNotImplementedError
   114  }
   115  
   116  // Find distribution name from /etc/release
   117  func parseReleaseFile() (string, error) {
   118  	b, err := ioutil.ReadFile("/etc/release")
   119  	if err != nil {
   120  		return "", err
   121  	}
   122  	s := string(b)
   123  	s = strings.TrimSpace(s)
   124  
   125  	var platform string
   126  
   127  	switch {
   128  	case strings.HasPrefix(s, "SmartOS"):
   129  		platform = "SmartOS"
   130  	case strings.HasPrefix(s, "OpenIndiana"):
   131  		platform = "OpenIndiana"
   132  	case strings.HasPrefix(s, "OmniOS"):
   133  		platform = "OmniOS"
   134  	case strings.HasPrefix(s, "Open Storage"):
   135  		platform = "NexentaStor"
   136  	case strings.HasPrefix(s, "Solaris"):
   137  		platform = "Solaris"
   138  	case strings.HasPrefix(s, "Oracle Solaris"):
   139  		platform = "Solaris"
   140  	default:
   141  		platform = strings.Fields(s)[0]
   142  	}
   143  
   144  	return platform, nil
   145  }
   146  
   147  // parseUnameOutput returns platformFamily, kernelVersion and platformVersion
   148  func parseUnameOutput(ctx context.Context) (string, string, string, error) {
   149  	uname, err := exec.LookPath("uname")
   150  	if err != nil {
   151  		return "", "", "", err
   152  	}
   153  
   154  	out, err := invoke.CommandWithContext(ctx, uname, "-srv")
   155  	if err != nil {
   156  		return "", "", "", err
   157  	}
   158  
   159  	fields := strings.Fields(string(out))
   160  	if len(fields) < 3 {
   161  		return "", "", "", fmt.Errorf("malformed `uname` output")
   162  	}
   163  
   164  	return fields[0], fields[1], fields[2], nil
   165  }
   166  
   167  func KernelVersionWithContext(ctx context.Context) (string, error) {
   168  	_, kernelVersion, _, err := parseUnameOutput(ctx)
   169  	return kernelVersion, err
   170  }
   171  
   172  func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) {
   173  	platform, err := parseReleaseFile()
   174  	if err != nil {
   175  		return "", "", "", err
   176  	}
   177  
   178  	platformFamily, _, platformVersion, err := parseUnameOutput(ctx)
   179  	if err != nil {
   180  		return "", "", "", err
   181  	}
   182  
   183  	return platform, platformFamily, platformVersion, nil
   184  }
   185  

View as plain text