1
0

feat: 删除不需要文件夹

This commit is contained in:
TsMask
2023-10-10 10:56:44 +08:00
parent ce7c3cae68
commit d173205528
154 changed files with 32276 additions and 1 deletions

852
features/state/getstate.go Normal file
View File

@@ -0,0 +1,852 @@
package state
import (
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/go-resty/resty/v2"
"github.com/gorilla/mux"
"ems.agt/lib/dborm"
"ems.agt/lib/global"
"ems.agt/lib/log"
"ems.agt/lib/services"
"ems.agt/restagent/config"
)
type CpuUsage struct {
NfCpuUsage uint16 `json:"nfCpuUsage"`
SysCpuUsage uint16 `json:"sysCpuUsage"`
}
type MemUsage struct {
TotalMem uint32 `json:"totalMem"`
NfUsedMem uint32 `json:"nfUsedMem"`
SysMemUsage uint16 `json:"sysMemUsage"`
}
type PartitionInfo struct {
Total uint32 `json:"total"` // MB
Used uint32 `json:"used"` // MB
}
type DiskSpace struct {
PartitionNum uint8 `json:"partitionNum"`
PartitionInfo []PartitionInfo `json:"partitionInfo"`
}
type HardwareInfo struct {
CPUs int `json:"cpus"`
Memory int `json:"memory"`
}
type SysState struct {
HostName string `json:"hostName"` // linux命令: hostname
OsInfo string `json:"osInfo"` // linux命令: uname -a
DbInfo string `json:"dbInfo"` // 网元如果有db, 显示数据库名和版本信息, OMC: mysql --version
Version string `json:"version"` // 软件版本信息: 16.1.1
IpAddr []string `json:"ipAddr"` // 网管的ipv4和ipv6列表
Port uint16 `json:"port"` // 用于网管的port
Capability uint32 `json:"capability"`
SerialNum string `json:"serialNum"`
ExpiryDate string `json:"expiryDate"`
HardwareInfo HardwareInfo `json:"hardwareInfo"`
CpuUsage CpuUsage `json:"cpuUsage"`
MemUsage MemUsage `json:"memUsage"`
DiskSpace DiskSpace `json:"diskSpace"`
//Timestamp string `json:"timestamp"`
}
type SystemState struct {
HostName string `json:"hostName"` // linux命令: hostname
OsInfo string `json:"osInfo"` // linux命令: uname -a
DbInfo string `json:"dbInfo"` // 网元如果有db, 显示数据库名和版本信息, OMC: mysql --version
Version string `json:"version"` // 软件版本信息: 16.1.1
IpAddr []string `json:"ipAddr"` // 网管的ipv4和ipv6列表
Port uint16 `json:"port"` // 用于网管的port
Capability uint32 `json:"capability"`
SerialNum string `json:"serialNum"`
ExpiryDate string `json:"expiryDate"`
HardwareInfo struct {
CPUs int `json:"cpus"` // 主机(裸机/虚拟机)的cpu个数
Memory int `json:"memory"` // 主机(裸机/虚拟机): 配置的内存
} `json:"hardwareInfo"`
CpuUsage struct {
NfCpuUsage uint16 `json:"nfCpuUsage"`
SysCpuUsage uint16 `json:"sysCpuUsage"`
} `json:"cpuUsage"`
MemUsage struct {
TotalMem uint32 `json:"totalMem"`
NfUsedMem uint32 `json:"nfUsedMem"`
SysMemUsage uint16 `json:"sysMemUsage"`
} `json:"memUsage"`
DiskSpace struct {
PartitionNum uint8 `json:"partitionNum"`
PartitionInfo []struct {
Total uint32 `json:"total"` // MB
Used uint32 `json:"used"` // MB
} `json:"partitionInfo"`
} `json:"diskSpace"`
//Timestamp string `json:"timestamp"`
}
type SystemInfo struct {
NeType string `json:"neType" map:"neType, omitempty"`
NeId string `json:"neId" map:"neId, omitempty"`
HostName string `json:"hostName" map:"hostName, omitempty"` // linux命令: hostname
OsInfo string `json:"osInfo" map:"osInfo, omitempty"` // linux命令: uname -a
DbInfo string `json:"dbInfo" map:"dbInfo, omitempty"` // 网元如果有db, 显示数据库名和版本信息, OMC: mysql --version
Version string `json:"version" map:"version, omitempty"` // 软件版本信息: 16.1.1
IpAddr string `json:"ipAddr" map:"ipAddr, omitempty"` // 网管的ipv4和ipv6列表
Port uint16 `json:"port" map:"port, omitempty"` // 用于网管的port
CPUs int `json:"cpus" map:"cpus, omitempty"`
TotalMem int `json:"totalMem" map:"totalMem, omitempty"`
PvFlag string `json:"pvFlag" map:"pvFlag, omitempty"`
Status string `json:"status" map:"status, omitempty"`
}
type LicenseInfo struct {
NeType string `json:"neType"`
NeId string `json:"neId"`
SerialNum string `json:"serialNum"`
Capability uint32 `json:"capability"`
CapUsed uint32 `json:"capUsed"`
FeatureEnabled []string `json:"featureEnabled"`
ExpiryDate string `json:"expiryDate"`
}
type Response struct {
Data interface{} `json:"data"`
}
var (
UriSysState = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/systemState"
UriSysState2 = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/{elementTypeValue}/systemState"
UriSysInfoAll = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/sysInfo"
UriSysInfoOne = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/sysInfo/{neType}/{neId}"
UriLicenseInfoAll = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/licenseInfo"
UriLicenseInfoOne = config.DefaultUriPrefix + "/systemManagement/{apiVersion}/licenseInfo/{neType}/{neId}"
CustomUriSysState = config.UriPrefix + "/systemManagement/{apiVersion}/elementType/{elementTypeValue}/objectType/systemState"
CustomUriSysState2 = config.UriPrefix + "/systemManagement/{apiVersion}/{elementTypeValue}/systemState"
CustomUriSysInfoAll = config.UriPrefix + "/systemManagement/{apiVersion}/sysInfo"
CustomUriSysInfoOne = config.UriPrefix + "/systemManagement/{apiVersion}/sysInfo/{neType}/{neId}"
CustomUriLicenseInfoAll = config.UriPrefix + "/systemManagement/{apiVersion}/licenseInfo"
CustomUriLicenseInfoOne = config.UriPrefix + "/systemManagement/{apiVersion}/licenseInfo/{neType}/{neId}"
)
var client = resty.New()
func init() {
/*
client.
SetTimeout(10 * time.Second).
SetRetryCount(1).
SetRetryWaitTime(1 * time.Second).
SetRetryMaxWaitTime(2 * time.Second).
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
return 0, errors.New("quota exceeded")
})
*/
client.SetTimeout(3 * time.Second)
}
func NeStatusEnumToStr(intStatus int) string {
switch intStatus {
case 0:
return "active"
case 1:
return "offline"
case 2:
return "standby"
case 3:
return "maintain"
default:
return "unkown"
}
}
// Get system state from NF/NFs
func GetOneLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("GetOneLicenseInfoFromNF processing... ")
data := make([]map[string]interface{}, 0)
vars := mux.Vars(r)
neType := vars["neType"]
neId := vars["neId"]
if neType == "" || neId == "" {
services.ResponseNotFound404UriNotExist(w, r)
return
}
token, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
log.Debug("AccessToken:", token)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Error("Failed to XormGetNeInfo:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if neInfo == nil {
err := global.ErrCMNotFoundTargetNE
log.Error(global.ErrCMNotFoundTargetNE)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Trace("neInfo:", neInfo)
//systemState := make(map[string]interface{})
systemState := &SysState{}
result := make(map[string]interface{})
//sysInfo := &SystemInfo{}
omcNeTypeLower := "omc"
if config.GetYamlConfig().OMC.NeType != "" {
omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType)
}
if neType != omcNeTypeLower {
log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower)
var requestURI2NF string
if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(neType) != "udm" {
var udmNEs []dborm.NeInfo
err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs)
if err != nil {
log.Error("Get system state from NF is failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
if len(udmNEs) > 0 {
udmNe := udmNEs[0]
hostUri := fmt.Sprintf("http://%s:%v", udmNe.Ip, udmNe.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(udmNe.NeType))
}
} else {
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(neInfo.NeType))
}
log.Debug("requestURI2NF:", requestURI2NF)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": token}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(requestURI2NF)
if err != nil {
log.Error("Get system state from NF is failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else {
log.Trace("resp.Body():", string(resp.Body()))
_ = json.Unmarshal(resp.Body(), &systemState)
log.Trace("systemState:", systemState)
capUsed := config.TDatas[neInfo.NeType].CapUsed
log.Tracef("neInfo.NeType:%s capUsed: %v", capUsed)
licenseInfo := &LicenseInfo{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
SerialNum: systemState.SerialNum,
Capability: systemState.Capability,
CapUsed: capUsed,
FeatureEnabled: config.TDatas[neInfo.NeType].FeatureEnabled,
ExpiryDate: systemState.ExpiryDate,
}
//neItem := strings.ToUpper(neType) + "/" + neId
result, err = global.ToMap(*licenseInfo, "json")
}
} else {
systemState := GetEMSState(neInfo.Ip)
licenseInfo := &LicenseInfo{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
SerialNum: systemState.SerialNum,
Capability: systemState.Capability,
CapUsed: config.TDatas[neInfo.NeType].CapUsed,
FeatureEnabled: config.TDatas[neInfo.NeType].FeatureEnabled,
ExpiryDate: systemState.ExpiryDate,
}
result, err = global.ToMap(*licenseInfo, "json")
// neItem := strings.ToUpper(neType) + "/" + neId
// result[neItem] = sysInfo
}
data = append(data, result)
log.Trace("data:", data)
var response Response
response.Data = data
services.ResponseWithJson(w, http.StatusOK, response)
}
// Get system state from NF/NFs
func GetAllLicenseInfoFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("GetAllLicenseInfoFromNF processing... ")
data := make([]map[string]interface{}, 0)
token, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
log.Debug("AccessToken:", token)
var neList []dborm.NeInfo
_, err = dborm.XormGetAllNeInfo(&neList)
omcNeTypeLower := "omc"
if config.GetYamlConfig().OMC.NeType != "" {
omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType)
}
for _, ne := range neList {
result := make(map[string]interface{})
log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower)
log.Debug("ne: ", ne)
//if strings.ToLower(ne.NeType) != omcNeTypeLower || !strings.Contains(r.RemoteAddr, ne.Ip) {
if strings.ToLower(ne.NeType) != omcNeTypeLower {
// hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port)
// requestURI2NF := fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
// hostUri, strings.ToLower(ne.NeType))
var requestURI2NF string
if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(ne.NeType) != "udm" {
var udmNEs []dborm.NeInfo
err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs)
if err != nil {
log.Error("Get system state from NF is failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
if len(udmNEs) > 0 {
udmNe := udmNEs[0]
hostUri := fmt.Sprintf("http://%s:%v", udmNe.Ip, udmNe.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(udmNe.NeType))
}
} else {
hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(ne.NeType))
}
log.Debug("requestURI2NF:", requestURI2NF)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": token}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(requestURI2NF)
if err != nil {
log.Error("Get system state from NF is failed:", err)
// errorMessage := services.ErrorMessage{
// ErrorCode: "1", ErrorInfo: "Internal server error, NF connnect refused",
// }
// //result["error"] = errorMessage
continue
} else {
systemState := &SysState{}
_ = json.Unmarshal(resp.Body(), &systemState)
licenseInfo := &LicenseInfo{
NeType: ne.NeType,
NeId: ne.NeId,
SerialNum: systemState.SerialNum,
Capability: systemState.Capability,
CapUsed: config.TDatas[ne.NeType].CapUsed,
FeatureEnabled: config.TDatas[ne.NeType].FeatureEnabled,
ExpiryDate: systemState.ExpiryDate,
}
result, err = global.ToMap(*licenseInfo, "json")
// neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId
// result[neItem] = sysInfo
}
} else {
systemState := GetEMSState(ne.Ip)
licenseInfo := &LicenseInfo{
NeType: ne.NeType,
NeId: ne.NeId,
SerialNum: systemState.SerialNum,
Capability: systemState.Capability,
CapUsed: config.TDatas[ne.NeType].CapUsed,
FeatureEnabled: config.TDatas[ne.NeType].FeatureEnabled,
ExpiryDate: systemState.ExpiryDate,
}
result, err = global.ToMap(*licenseInfo, "json")
// neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId
// result[neItem] = sysInfo
}
data = append(data, result)
log.Trace("data:", data)
}
var response Response
response.Data = data
services.ResponseWithJson(w, http.StatusOK, response)
}
// Get system state from NF/NFs
func GetOneSysinfoFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("GetOneSysinfoFromNF processing... ")
data := make([]map[string]interface{}, 0)
vars := mux.Vars(r)
neType := vars["neType"]
neId := vars["neId"]
if neType == "" || neId == "" {
services.ResponseNotFound404UriNotExist(w, r)
return
}
token, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
log.Debug("AccessToken:", token)
neInfo, err := dborm.XormGetNeInfo(neType, neId)
if err != nil {
log.Error("Failed to XormGetNeInfo:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else if neInfo == nil {
err := global.ErrCMNotFoundTargetNE
log.Error(global.ErrCMNotFoundTargetNE)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
log.Trace("neInfo:", neInfo)
//systemState := make(map[string]interface{})
systemState := &SysState{}
result := make(map[string]interface{})
//sysInfo := &SystemInfo{}
omcNeTypeLower := "omc"
if config.GetYamlConfig().OMC.NeType != "" {
omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType)
}
if neType != omcNeTypeLower {
log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower)
var requestURI2NF string
if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(neType) != "udm" {
var udmNEs []dborm.NeInfo
err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs)
if err != nil {
log.Error("Get system state from NF is failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
if len(udmNEs) > 0 {
udmNe := udmNEs[0]
hostUri := fmt.Sprintf("http://%s:%v", udmNe.Ip, udmNe.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(udmNe.NeType))
}
} else {
hostUri := fmt.Sprintf("http://%s:%v", neInfo.Ip, neInfo.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(neInfo.NeType))
}
log.Debug("requestURI2NF:", requestURI2NF)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": token}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(requestURI2NF)
if err != nil {
log.Error("Get system state from NF is failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
} else {
log.Trace("resp.Body():", string(resp.Body()))
_ = json.Unmarshal(resp.Body(), &systemState)
log.Trace("systemState:", systemState)
hostName := "5gc"
if systemState.HostName != "" {
hostName = systemState.HostName
}
osInfo := "Linux 5gc 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 GNU/Linux"
if systemState.OsInfo != "" {
osInfo = systemState.OsInfo
}
dbInfo := "adb v1.0.1"
if systemState.OsInfo != "" {
dbInfo = systemState.DbInfo
}
port, _ := strconv.Atoi(neInfo.Port)
cpus := 4
if systemState.HardwareInfo.CPUs != 0 {
cpus = systemState.HardwareInfo.CPUs
}
totalMem := 34029125632
if systemState.HardwareInfo.Memory != 0 {
totalMem = systemState.HardwareInfo.Memory
}
sysInfo := &SystemInfo{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
HostName: hostName,
OsInfo: osInfo,
DbInfo: dbInfo,
Version: systemState.Version,
IpAddr: neInfo.Ip,
Port: uint16(port),
CPUs: cpus,
TotalMem: totalMem,
PvFlag: neInfo.PvFlag,
Status: NeStatusEnumToStr(neInfo.Status),
}
//neItem := strings.ToUpper(neType) + "/" + neId
result, err = global.ToMap(*sysInfo, "json")
}
} else {
systemState := GetEMSState(neInfo.Ip)
sysInfo := &SystemInfo{
NeType: neInfo.NeType,
NeId: neInfo.NeId,
HostName: systemState.HostName,
OsInfo: systemState.OsInfo,
DbInfo: systemState.DbInfo,
Version: systemState.Version,
IpAddr: neInfo.Ip,
Port: systemState.Port,
CPUs: systemState.HardwareInfo.CPUs,
TotalMem: systemState.HardwareInfo.Memory,
PvFlag: neInfo.PvFlag,
Status: NeStatusEnumToStr(neInfo.Status),
}
result, err = global.ToMap(*sysInfo, "json")
// neItem := strings.ToUpper(neType) + "/" + neId
// result[neItem] = sysInfo
}
data = append(data, result)
log.Trace("data:", data)
var response Response
response.Data = data
services.ResponseWithJson(w, http.StatusOK, response)
}
// Get system state from NF/NFs
func GetAllSysinfoFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("GetAllSysinfoFromNF processing... ")
data := make([]map[string]interface{}, 0)
token, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
log.Debug("AccessToken:", token)
var neList []dborm.NeInfo
_, err = dborm.XormGetAllNeInfo(&neList)
omcNeTypeLower := "omc"
if config.GetYamlConfig().OMC.NeType != "" {
omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType)
}
for _, ne := range neList {
result := make(map[string]interface{})
log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower)
log.Debug("ne: ", ne)
//if strings.ToLower(ne.NeType) != omcNeTypeLower || !strings.Contains(r.RemoteAddr, ne.Ip) {
if strings.ToLower(ne.NeType) != omcNeTypeLower {
// hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port)
// requestURI2NF := fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
// hostUri, strings.ToLower(ne.NeType))
var requestURI2NF string
if config.GetYamlConfig().OMC.TestMode == true && strings.ToLower(ne.NeType) != "udm" {
var udmNEs []dborm.NeInfo
err := dborm.XormGetNeInfoByNeType("UDM", &udmNEs)
if err != nil {
log.Error("Get system state from NF is failed:", err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
if len(udmNEs) > 0 {
udmNe := udmNEs[0]
hostUri := fmt.Sprintf("http://%s:%v", udmNe.Ip, udmNe.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(udmNe.NeType))
}
} else {
hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port)
requestURI2NF = fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, strings.ToLower(ne.NeType))
}
log.Debug("requestURI2NF:", requestURI2NF)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": token}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(requestURI2NF)
if err != nil {
log.Error("Get system state from NF is failed:", err)
// errorMessage := services.ErrorMessage{
// ErrorCode: "1", ErrorInfo: "Internal server error, NF connnect refused",
// }
// //result["error"] = errorMessage
continue
} else {
systemState := &SysState{}
_ = json.Unmarshal(resp.Body(), &systemState)
hostName := "5gc"
if systemState.HostName != "" {
hostName = systemState.HostName
}
osInfo := "Linux 5gc 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 GNU/Linux"
if systemState.OsInfo != "" {
osInfo = systemState.OsInfo
}
dbInfo := "adb v1.0.1"
if systemState.OsInfo != "" {
dbInfo = systemState.DbInfo
}
port, _ := strconv.Atoi(ne.Port)
cpus := 4
if systemState.HardwareInfo.CPUs != 0 {
cpus = systemState.HardwareInfo.CPUs
}
totalMem := 34029125632
if systemState.HardwareInfo.Memory != 0 {
totalMem = systemState.HardwareInfo.Memory
}
sysInfo := &SystemInfo{
NeType: ne.NeType,
NeId: ne.NeId,
HostName: hostName,
OsInfo: osInfo,
DbInfo: dbInfo,
Version: systemState.Version,
IpAddr: ne.Ip,
Port: uint16(port),
CPUs: cpus,
TotalMem: totalMem,
PvFlag: ne.PvFlag,
Status: NeStatusEnumToStr(ne.Status),
}
// neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId
// result[neItem] = sysInfo
result, err = global.ToMap(*sysInfo, "json")
}
} else {
port, _ := strconv.Atoi(ne.Port)
systemState := GetEMSState(ne.Ip)
sysInfo := &SystemInfo{
NeType: ne.NeType,
NeId: ne.NeId,
HostName: systemState.HostName,
OsInfo: systemState.OsInfo,
DbInfo: systemState.DbInfo,
Version: systemState.Version,
IpAddr: ne.Ip,
Port: (uint16(port)),
CPUs: systemState.HardwareInfo.CPUs,
TotalMem: systemState.HardwareInfo.Memory,
PvFlag: ne.PvFlag,
Status: NeStatusEnumToStr(ne.Status),
}
// neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId
// result[neItem] = sysInfo
result, err = global.ToMap(*sysInfo, "json")
}
data = append(data, result)
log.Trace("data:", data)
}
var response Response
response.Data = data
services.ResponseWithJson(w, http.StatusOK, response)
}
// Get system state from NF/NFs
func GetStateFromNF(w http.ResponseWriter, r *http.Request) {
log.Debug("GetStateFromNF processing... ")
data := make([]map[string]interface{}, 0)
vars := mux.Vars(r)
neType := vars["elementTypeValue"]
var neList []dborm.NeInfo
if neType == "" {
services.ResponseNotFound404UriNotExist(w, r)
return
}
token, err := services.CheckFrontValidRequest(w, r)
if err != nil {
log.Error("Request error:", err)
return
}
log.Debug("AccessToken:", token)
switch strings.ToLower(neType) {
case "all":
// query all NFs
// create rest client
restHostPort := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
getNeInfoPattern := fmt.Sprintf(config.UriPrefix+"/databaseManagement/v1/elementType/%s/objectType/ne_info",
config.GetYamlConfig().Database.Name)
getNeInfoURI := restHostPort + getNeInfoPattern + "?WHERE=status='0'"
log.Debug("getNeInfoPattern:", getNeInfoPattern)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"AccessToken": token}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(getNeInfoURI)
if err != nil {
log.Error("Get ne_info from DB is failed:", err)
services.ResponseInternalServerError500NFConnectRefused(w)
return
}
neList, _ = dborm.XormParseResult(resp.Body())
default:
restHostPort := fmt.Sprintf("http://127.0.0.1:%d", config.GetYamlConfig().Rest[0].Port)
getNeInfoPattern := fmt.Sprintf(config.UriPrefix+"/databaseManagement/v1/elementType/%s/objectType/ne_info",
config.GetYamlConfig().Database.Name)
getNeInfoURI := restHostPort + getNeInfoPattern
neId := services.GetUriParamString(r, "ne_id", ",", true, false)
if neId == "" {
getNeInfoURI = getNeInfoURI + fmt.Sprintf("?WHERE=status='0'+and+ne_type='%s'", neType)
} else {
getNeInfoURI = getNeInfoURI + fmt.Sprintf("?WHERE=status='0'+and+ne_type='%v'+and+ne_id+in+%v", neType, neId)
}
log.Debug("getNeInfoURI:", getNeInfoURI)
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": token}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(getNeInfoURI)
if err != nil {
log.Error("Get ne_info from DB is failed:", err)
services.ResponseInternalServerError500NFConnectRefused(w)
return
}
neList, _ = dborm.XormParseResult(resp.Body())
}
omcNeTypeLower := "omc"
if config.GetYamlConfig().OMC.NeType != "" {
omcNeTypeLower = strings.ToLower(config.GetYamlConfig().OMC.NeType)
}
for _, ne := range neList {
result := make(map[string]interface{})
log.Debugf("r.RemoteAddr: %s omcNeTypeLower: %s", r.RemoteAddr, omcNeTypeLower)
log.Debug("ne: ", ne)
//if strings.ToLower(ne.NeType) != omcNeTypeLower || !strings.Contains(r.RemoteAddr, ne.Ip) {
if strings.ToLower(ne.NeType) != omcNeTypeLower {
hostUri := fmt.Sprintf("http://%s:%v", ne.Ip, ne.Port)
requestURI2NF := fmt.Sprintf("%s/api/rest/systemManagement/v1/elementType/%s/objectType/systemState",
hostUri, ne.NeType)
log.Debug("requestURI2NF:", requestURI2NF)
result["ipAddress"] = ne.Ip
resp, err := client.R().
EnableTrace().
SetHeaders(map[string]string{"accessToken": token}).
SetHeaders(map[string]string{"User-Agent": config.GetDefaultUserAgent()}).
SetHeaders(map[string]string{"Content-Type": "application/json;charset=UTF-8"}).
Get(requestURI2NF)
if err != nil {
log.Error("Get system state from NF is failed:", err)
errorMessage := services.ErrorMessage{
ErrorCode: "1", ErrorInfo: "Internal server error, NF connnect refused",
}
result["error"] = errorMessage
} else {
systemState := make(map[string]interface{})
_ = json.Unmarshal(resp.Body(), &systemState)
result["systemState"] = systemState
}
} else {
result["ipAddress"] = ne.Ip
emsState := GetEMSState(ne.Ip)
result["systemState"] = emsState
}
neItem := strings.ToUpper(ne.NeType) + "/" + ne.NeId
mapState := make(map[string]interface{})
mapState[neItem] = result
data = append(data, mapState)
log.Trace("data:", data)
}
var response Response
response.Data = data
services.ResponseWithJson(w, http.StatusOK, response)
}
func GetEMSState(ip string) *SysState {
log.Debug("GetEMSState processing... ")
sysInfo := new(SysInfo)
err := GetSysInfo(sysInfo)
if err != nil {
log.Error("Failed to GetSysInfo:", err)
return nil
}
cpuUsage := &CpuUsage{
NfCpuUsage: sysInfo.MyCpuPercent,
SysCpuUsage: sysInfo.SysCpuPercent,
}
memUsage := &MemUsage{
TotalMem: sysInfo.SysTotalRam,
NfUsedMem: sysInfo.MyUsedRam,
SysMemUsage: sysInfo.SysRamUsedPercent,
}
diskSpace := &DiskSpace{
PartitionNum: sysInfo.PartitionNum,
PartitionInfo: sysInfo.PartitionInfo,
}
version := "16.1.1"
if global.Version != "" {
version = global.Version
}
hostName, _ := os.Hostname()
emsState := &SysState{
HostName: hostName,
OsInfo: getUnameStr(),
DbInfo: "mysql Ver 15.1 Distrib 10.3.35-MariaDB, for Linux (aarch64) using readline 5.1",
IpAddr: []string{ip},
Port: 3030,
Version: version,
Capability: 9999999,
SerialNum: config.GetYamlConfig().OMC.Sn,
ExpiryDate: "-",
HardwareInfo: HardwareInfo{CPUs: getCpuNumber(), Memory: getTotalMemory()},
CpuUsage: *cpuUsage,
MemUsage: *memUsage,
DiskSpace: *diskSpace,
}
//getSystemInfo()
return emsState
}

View File

@@ -0,0 +1,243 @@
//go:build linux
// +build linux
package state
import (
"encoding/binary"
"fmt"
"os"
"runtime"
"syscall"
"time"
"ems.agt/lib/log"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/process"
)
type SysInfo struct {
SysCpuPercent uint16 // x%
MyCpuPercent uint16 // x%, CPU percent of current proccess
SysTotalRam uint32 // KB
MyUsedRam uint32 // RAM usage of current proccess, KB
SysRamUsedPercent uint16 // x%
PartitionNum byte
PartitionInfo []PartitionInfo // usage of each partition
}
const MAX_PARTITION_NUM byte = 32
func GetSysStat() ([]byte, int) {
// Get sys info
var sysInfo SysInfo
err := GetSysInfo(&sysInfo)
if err != nil {
return nil, 0
}
//log.Tracef("current sys info: %v", sysInfo)
// build ems buffer
var data []byte = make([]byte, 1024)
var len int
var i byte
binary.BigEndian.PutUint16(data[0:], sysInfo.MyCpuPercent) //x% * 100
binary.BigEndian.PutUint16(data[2:], sysInfo.SysCpuPercent) //x% * 100
binary.BigEndian.PutUint32(data[4:], sysInfo.SysTotalRam) // KB
binary.BigEndian.PutUint32(data[8:], sysInfo.MyUsedRam) // KB
binary.BigEndian.PutUint16(data[12:], sysInfo.SysRamUsedPercent) //x% * 100
data[14] = sysInfo.PartitionNum
for i = 0; i < sysInfo.PartitionNum; i++ {
binary.BigEndian.PutUint32(data[15+8*(i):], sysInfo.PartitionInfo[i].Total) // MB
binary.BigEndian.PutUint32(data[15+8*(i)+4:], sysInfo.PartitionInfo[i].Used) // MB
}
len = int(15 + 8*sysInfo.PartitionNum)
//log.Tracef("current sys stat buf: %v, len: %d", data, len)
return data, len
}
var pProc *process.Process = nil
func GetSYsCpuPercent() float64 {
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
return 0.0
} else {
return totalPercent[0]
}
}
func GetSysInfo(sysInfo *SysInfo) error {
// sys cpu percent
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
sysInfo.SysCpuPercent = 0
} else {
sysInfo.SysCpuPercent = uint16(totalPercent[0] * 100)
}
if pProc == nil {
checkPid := os.Getpid()
pProc, err = process.NewProcess(int32(checkPid))
if err != nil {
log.Tracef("get process info error %v", err)
return err
}
}
// self cpu percent
percent, err := pProc.Percent(0) //(2*time.Second)
if err != nil {
log.Tracef("get process cpu percent error %v", err)
sysInfo.MyCpuPercent = 0
} else {
sysInfo.MyCpuPercent = uint16(percent * 100)
}
// self RAM(KB)
myRam, err := pProc.MemoryInfo()
if err != nil {
log.Tracef("get self memory info error %v", err)
sysInfo.MyUsedRam = 0
} else {
sysInfo.MyUsedRam = uint32(myRam.RSS / 1024)
}
// system RAM(KB)
sysRam, err := mem.VirtualMemory()
if err != nil {
log.Tracef("gett sys memory info error %v", err)
sysInfo.SysTotalRam = 0
sysInfo.SysRamUsedPercent = 0
} else {
sysInfo.SysTotalRam = uint32(sysRam.Total / 1024)
sysInfo.SysRamUsedPercent = uint16(sysRam.UsedPercent * 100)
}
// partition usage
GetPartitions(sysInfo)
return nil
}
func getProcess() process.Process {
checkPid := os.Getpid()
ret, _ := process.NewProcess(int32(checkPid))
return *ret
}
func GetSystemCpuInfo() {
physicalCnt, _ := cpu.Counts(false)
logicalCnt, _ := cpu.Counts(true)
log.Tracef("physical count:%d logical count:%d", physicalCnt, logicalCnt)
totalPercent, _ := cpu.Percent(3*time.Second, false) // per cpu is false
perPercents, _ := cpu.Percent(3*time.Second, true) // per cpu is true
log.Tracef("total percent:%v per percents:%v", totalPercent, perPercents)
}
func GetProcessCpuPercent() {
p := getProcess()
percent, err := p.Percent(0)
if err != nil {
log.Tracef("error %v", err)
}
numcpu := runtime.NumCPU()
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
if percent < 0.0 {
log.Tracef("Err CPU Percent of Process: %f, CPU num: %d", percent, numcpu)
} else {
log.Tracef("get process CPU percent: %f, CPU num: %d", percent, numcpu)
}
}
func GetProcessMemoryInfo() {
p := getProcess()
v, err := p.MemoryInfo()
if err != nil {
log.Tracef("getting memory info error %v", err)
}
log.Tracef("get process memory info %v", v)
info, _ := mem.VirtualMemory()
fmt.Println(info)
}
func GetPartitions(sysInfo *SysInfo) {
sysInfo.PartitionNum = 0
//sysInfo.PartitionInfo = make([]PartitionInfo, MAX_PARTITION_NUM, MAX_PARTITION_NUM)
infos, _ := disk.Partitions(true)
for _, info := range infos {
GetOnePartitionUsage(info.Mountpoint, sysInfo)
if sysInfo.PartitionNum >= MAX_PARTITION_NUM {
break
}
}
}
func GetOnePartitionUsage(path string, sysInfo *SysInfo) int {
info, err := disk.Usage(path)
if err != nil {
return -1
}
if info.Total <= 0 { // info.Used/(1024 * 1024)MB
return 0
}
var partition PartitionInfo
partition.Total = uint32(info.Total / 1024 / 1024)
partition.Used = uint32(info.Used / 1024 / 1024)
sysInfo.PartitionInfo = append(sysInfo.PartitionInfo, partition)
sysInfo.PartitionNum++
/*data, err := json.MarshalIndent(info, "", " ")
if err != nil {
return -1
}
fmt.Println(string(data))*/
return 1
}
func getOS() string {
var osname string
if runtime.GOOS == "linux" {
osname = "GNU/Linux"
}
return osname
}
func utsnameToString(unameArray [65]int8) string {
var byteString [65]byte
var indexLength int
for ; unameArray[indexLength] != 0 && indexLength < 65; indexLength++ {
byteString[indexLength] = uint8(unameArray[indexLength])
}
return string(byteString[:indexLength])
}
func getUnameStr() string {
var utsname = syscall.Utsname{}
err := syscall.Uname(&utsname)
if err == nil {
name := utsnameToString(utsname.Sysname)
node := utsnameToString(utsname.Nodename)
release := utsnameToString(utsname.Release)
version := utsnameToString(utsname.Version)
machine := utsnameToString(utsname.Machine)
//domain:= utsnameToString(utsname.Domainname)
osName := getOS()
return fmt.Sprintf("%s %s %s %s %s %s", name, node,
release, version, machine, osName)
}
return ""
}

View File

@@ -0,0 +1,231 @@
//go:build windows
// +build windows
package state
import (
"encoding/binary"
"fmt"
"os"
"runtime"
"syscall"
"time"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/mem"
"github.com/shirou/gopsutil/process"
)
type SysInfo struct {
SysCpuPercent uint16 // x%
MyCpuPercent uint16 // x%, CPU percent of current proccess
SysTotalRam uint32 // KB
MyUsedRam uint32 // RAM usage of current proccess, KB
SysRamUsedPercent uint16 // x%
PartitionNum byte
PartitionInfo []PartitionInfo // usage of each partition
}
const MAX_PARTITION_NUM byte = 32
func GetSysStat() ([]byte, int) {
// Get sys info
var sysInfo SysInfo
err := GetSysInfo(&sysInfo)
if err != nil {
return nil, 0
}
//fmt.Printf("current sys info: %v", sysInfo)
// build ems buffer
var data []byte = make([]byte, 1024)
var len int
var i byte
binary.BigEndian.PutUint16(data[0:], sysInfo.MyCpuPercent) //x% * 100
binary.BigEndian.PutUint16(data[2:], sysInfo.SysCpuPercent) //x% * 100
binary.BigEndian.PutUint32(data[4:], sysInfo.SysTotalRam) // KB
binary.BigEndian.PutUint32(data[8:], sysInfo.MyUsedRam) // KB
binary.BigEndian.PutUint16(data[12:], sysInfo.SysRamUsedPercent) //x% * 100
data[14] = sysInfo.PartitionNum
for i = 0; i < sysInfo.PartitionNum; i++ {
binary.BigEndian.PutUint32(data[15+8*(i):], sysInfo.PartitionInfo[i].Total) // MB
binary.BigEndian.PutUint32(data[15+8*(i)+4:], sysInfo.PartitionInfo[i].Used) // MB
}
len = int(15 + 8*sysInfo.PartitionNum)
//fmt.Printf("current sys stat buf: %v, len: %d", data, len)
return data, len
}
var pProc *process.Process = nil
func GetSYsCpuPercent() float64 {
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
return 0.0
} else {
return totalPercent[0]
}
}
func GetSysInfo(sysInfo *SysInfo) error {
// sys cpu percent
totalPercent, err := cpu.Percent(0, false) //(2*time.Second, false)
if err != nil {
sysInfo.SysCpuPercent = 0
} else {
sysInfo.SysCpuPercent = uint16(totalPercent[0] * 100)
}
if pProc == nil {
checkPid := os.Getpid()
pProc, err = process.NewProcess(int32(checkPid))
if err != nil {
fmt.Printf("get process info error %v", err)
return err
}
}
// self cpu percent
percent, err := pProc.Percent(0) //(2*time.Second)
if err != nil {
fmt.Printf("get process cpu percent error %v", err)
sysInfo.MyCpuPercent = 0
} else {
sysInfo.MyCpuPercent = uint16(percent * 100)
}
// self RAM(KB)
myRam, err := pProc.MemoryInfo()
if err != nil {
fmt.Printf("get self memory info error %v", err)
sysInfo.MyUsedRam = 0
} else {
sysInfo.MyUsedRam = uint32(myRam.RSS / 1024)
}
// system RAM(KB)
sysRam, err := mem.VirtualMemory()
if err != nil {
fmt.Printf("gett sys memory info error %v", err)
sysInfo.SysTotalRam = 0
sysInfo.SysRamUsedPercent = 0
} else {
sysInfo.SysTotalRam = uint32(sysRam.Total / 1024)
sysInfo.SysRamUsedPercent = uint16(sysRam.UsedPercent * 100)
}
// partition usage
GetPartitions(sysInfo)
return nil
}
func getProcess() process.Process {
checkPid := os.Getpid()
ret, _ := process.NewProcess(int32(checkPid))
return *ret
}
func GetSystemCpuInfo() {
physicalCnt, _ := cpu.Counts(false)
logicalCnt, _ := cpu.Counts(true)
fmt.Printf("physical count:%d logical count:%d\n", physicalCnt, logicalCnt)
totalPercent, _ := cpu.Percent(3*time.Second, false) // per cpu is false
perPercents, _ := cpu.Percent(3*time.Second, true) // per cpu is true
fmt.Printf("total percent:%v per percents:%v\n", totalPercent, perPercents)
}
func GetProcessCpuPercent() {
p := getProcess()
percent, err := p.Percent(0)
if err != nil {
fmt.Printf("error %v", err)
}
numcpu := runtime.NumCPU()
// if percent < 0.0 || percent > 100.0*float64(numcpu) { // TODO
if percent < 0.0 {
fmt.Printf("Err CPU Percent of Process: %f, CPU num: %d", percent, numcpu)
} else {
fmt.Printf("get process CPU percent: %f, CPU num: %d", percent, numcpu)
}
}
func GetProcessMemoryInfo() {
p := getProcess()
v, err := p.MemoryInfo()
if err != nil {
fmt.Printf("getting memory info error %v", err)
}
fmt.Printf("get process memory info %v\n", v)
info, _ := mem.VirtualMemory()
fmt.Println(info)
}
func GetPartitions(sysInfo *SysInfo) {
sysInfo.PartitionNum = 0
//sysInfo.PartitionInfo = make([]PartitionInfo, MAX_PARTITION_NUM, MAX_PARTITION_NUM)
infos, _ := disk.Partitions(true)
for _, info := range infos {
GetOnePartitionUsage(info.Mountpoint, sysInfo)
if sysInfo.PartitionNum >= MAX_PARTITION_NUM {
break
}
}
}
func GetOnePartitionUsage(path string, sysInfo *SysInfo) int {
info, err := disk.Usage(path)
if err != nil {
return -1
}
if info.Total <= 0 { // info.Used/(1024 * 1024)MB
return 0
}
var partition PartitionInfo
partition.Total = uint32(info.Total / 1024 / 1024)
partition.Used = uint32(info.Used / 1024 / 1024)
sysInfo.PartitionInfo = append(sysInfo.PartitionInfo, partition)
sysInfo.PartitionNum++
/*data, err := json.MarshalIndent(info, "", " ")
if err != nil {
return -1
}
fmt.Println(string(data))*/
return 1
}
func getOS() string {
var osname string
if runtime.GOOS == "linux" {
osname = "GNU/Linux"
}
return osname
}
func utsnameToString(unameArray [65]int8) string {
var byteString [65]byte
var indexLength int
for ; unameArray[indexLength] != 0 && indexLength < 65; indexLength++ {
byteString[indexLength] = uint8(unameArray[indexLength])
}
return string(byteString[:indexLength])
}
func getUnameStr() string {
osInfo, _ := syscall.GetVersion()
return fmt.Sprintf("Widnows %d", osInfo)
}

74
features/state/sysinfo.go Normal file
View File

@@ -0,0 +1,74 @@
package state
import (
"ems.agt/lib/log"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/disk"
"github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/mem"
)
func getSystemInfo() {
// 获取主机信息
hostInfo, err := host.Info()
if err != nil {
log.Errorf("Failed to get host info: %v", err)
return
}
log.Tracef("Host info: %+v", hostInfo)
// 获取CPU信息
cpuInfo, err := cpu.Info()
if err != nil {
log.Errorf("Failed to get CPU info: %v", err)
return
}
log.Tracef("CPU info: %+v", cpuInfo)
// 获取内存信息
memInfo, err := mem.VirtualMemory()
if err != nil {
log.Errorf("Failed to get memory info: %v", err)
return
}
log.Tracef("Memory info: %+v", memInfo)
// 获取磁盘分区信息
diskPartitions, err := disk.Partitions(true)
if err != nil {
log.Errorf("Failed to get disk partitions: %v", err)
return
}
log.Tracef("Disk partitions: %+v", diskPartitions)
for _, partition := range diskPartitions {
// 获取每个磁盘分区的使用情况
usage, err := disk.Usage(partition.Mountpoint)
if err != nil {
log.Errorf("Failed to get disk usage for %s: %v", partition.Mountpoint, err)
continue
}
log.Tracef("%s usage: %+v", partition.Mountpoint, usage)
}
}
func getCpuNumber() int {
// 获取CPU信息
cpuInfo, err := cpu.Info()
if err != nil {
log.Errorf("Failed to get CPU info: %v", err)
return 0
}
log.Tracef("CPU info: %+v", cpuInfo)
return len(cpuInfo)
}
func getTotalMemory() int {
// 获取内存信息
memInfo, err := mem.VirtualMemory()
if err != nil {
log.Errorf("Failed to get memory info: %v", err)
return 0
}
log.Tracef("Memory info: %+v", memInfo)
return int(memInfo.Total)
}