181 lines
4.1 KiB
Go
181 lines
4.1 KiB
Go
package sysinfo
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"code.thetadev.de/TSGRain/SEBRAUC/src/util"
|
|
)
|
|
|
|
type SystemInfo struct {
|
|
Hostname string `json:"hostname"`
|
|
OsName string `json:"os_name"`
|
|
OsVersion string `json:"os_version"`
|
|
Uptime int `json:"uptime"`
|
|
RaucCompatible string `json:"rauc_compatible"`
|
|
RaucVariant string `json:"rauc_variant"`
|
|
RaucRootfs map[string]Rootfs `json:"rauc_rootfs"`
|
|
}
|
|
|
|
type Rootfs struct {
|
|
Device string `json:"device"`
|
|
Type string `json:"type"`
|
|
bootname string
|
|
Mountpoint *string `json:"mountpoint"`
|
|
Bootable bool `json:"bootable"`
|
|
Booted bool `json:"booted"`
|
|
Primary bool `json:"primary"`
|
|
}
|
|
|
|
type raucInfo struct {
|
|
Compatible string `json:"compatible"`
|
|
Variant string `json:"variant"`
|
|
Booted string `json:"booted"`
|
|
BootPrimary string `json:"boot_primary"`
|
|
Slots []map[string]raucFS `json:"slots"`
|
|
}
|
|
|
|
type raucFS struct {
|
|
Class string `json:"class"`
|
|
Device string `json:"device"`
|
|
Type string `json:"type"`
|
|
Bootname string `json:"bootname"`
|
|
State string `json:"state"`
|
|
Mountpoint *string `json:"mountpoint"`
|
|
BootStatus string `json:"boot_status"`
|
|
}
|
|
|
|
type osRelease struct {
|
|
OsName string `json:"os_name"`
|
|
OsVersion string `json:"os_version"`
|
|
}
|
|
|
|
var (
|
|
rexpOsName = regexp.MustCompile(`(?m)^NAME="(.+)"`)
|
|
rexpOsVersion = regexp.MustCompile(`(?m)^VERSION="(.+)"`)
|
|
rexpUptime = regexp.MustCompile(`^\d+`)
|
|
)
|
|
|
|
func parseRaucInfo(raucInfoJson []byte) (raucInfo, error) {
|
|
res := raucInfo{}
|
|
err := json.Unmarshal(raucInfoJson, &res)
|
|
return res, err
|
|
}
|
|
|
|
func parseOsRelease(osReleaseFile string) (osRelease, error) {
|
|
osReleaseTxt, err := os.ReadFile(osReleaseFile)
|
|
if err != nil {
|
|
return osRelease{}, err
|
|
}
|
|
|
|
nameMatch := rexpOsName.FindSubmatch(osReleaseTxt)
|
|
versionMatch := rexpOsVersion.FindSubmatch(osReleaseTxt)
|
|
|
|
name := ""
|
|
if nameMatch != nil {
|
|
name = string(nameMatch[1])
|
|
}
|
|
|
|
version := ""
|
|
if versionMatch != nil {
|
|
version = string(versionMatch[1])
|
|
}
|
|
|
|
return osRelease{
|
|
OsName: name,
|
|
OsVersion: version,
|
|
}, nil
|
|
}
|
|
|
|
func mapRootfs(rinf raucInfo) map[string]Rootfs {
|
|
res := make(map[string]Rootfs)
|
|
|
|
for _, slot := range rinf.Slots {
|
|
for name, fs := range slot {
|
|
if fs.Class == "rootfs" {
|
|
res[name] = Rootfs{
|
|
Device: fs.Device,
|
|
Type: fs.Type,
|
|
bootname: fs.Bootname,
|
|
Mountpoint: fs.Mountpoint,
|
|
Bootable: fs.BootStatus == "good",
|
|
Booted: fs.State == "booted",
|
|
Primary: rinf.BootPrimary == name,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
func getFSNameFromBootname(rfslist map[string]Rootfs, bootname string) string {
|
|
for name, rfs := range rfslist {
|
|
if rfs.bootname == bootname {
|
|
return name
|
|
}
|
|
}
|
|
return "n/a"
|
|
}
|
|
|
|
func mapSysinfo(rinf raucInfo, osr osRelease, uptime int, hostname string) SystemInfo {
|
|
rfslist := mapRootfs(rinf)
|
|
|
|
return SystemInfo{
|
|
Hostname: hostname,
|
|
OsName: osr.OsName,
|
|
OsVersion: osr.OsVersion,
|
|
Uptime: uptime,
|
|
RaucCompatible: rinf.Compatible,
|
|
RaucVariant: rinf.Variant,
|
|
RaucRootfs: rfslist,
|
|
}
|
|
}
|
|
|
|
func getUptime() (int, error) {
|
|
uptimeRaw, err := os.ReadFile("/proc/uptime")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
uptimeChars := rexpUptime.Find(uptimeRaw)
|
|
return strconv.Atoi(string(uptimeChars))
|
|
}
|
|
|
|
func getHostname() string {
|
|
hostname, err := os.ReadFile("/etc/hostname")
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(string(hostname))
|
|
}
|
|
|
|
func GetSysinfo() (SystemInfo, error) {
|
|
cmd := util.CommandFromString(util.RaucCmd + " status --output-format=json")
|
|
rinfJson, err := cmd.Output()
|
|
if err != nil {
|
|
return SystemInfo{}, err
|
|
}
|
|
|
|
rinf, err := parseRaucInfo(rinfJson)
|
|
if err != nil {
|
|
return SystemInfo{}, err
|
|
}
|
|
|
|
osinf, err := parseOsRelease("/etc/os-release")
|
|
if err != nil {
|
|
return SystemInfo{}, err
|
|
}
|
|
|
|
uptime, err := getUptime()
|
|
if err != nil {
|
|
return SystemInfo{}, err
|
|
}
|
|
|
|
hostname := getHostname()
|
|
|
|
return mapSysinfo(rinf, osinf, uptime, hostname), nil
|
|
}
|