Refactor health data structure (#11914)

This feature comes with simplified data structures and versioning support.

Signed-off-by: Bala.FA <bala.gluster@gmail.com>
This commit is contained in:
Bala FA
2021-06-01 21:25:49 +05:30
committed by GitHub
parent 8347db8be3
commit 120951d9e9
9 changed files with 368 additions and 829 deletions

View File

@@ -1366,6 +1366,105 @@ func (a adminAPIHandlers) KMSKeyStatusHandler(w http.ResponseWriter, r *http.Req
writeSuccessResponseJSON(w, resp)
}
func getServerInfo(ctx context.Context, r *http.Request) madmin.InfoMessage {
kmsStat := fetchKMSStatus()
ldap := madmin.LDAP{}
if globalLDAPConfig.Enabled {
ldapConn, err := globalLDAPConfig.Connect()
if err != nil {
ldap.Status = string(madmin.ItemOffline)
} else if ldapConn == nil {
ldap.Status = "Not Configured"
} else {
// Close ldap connection to avoid leaks.
ldapConn.Close()
ldap.Status = string(madmin.ItemOnline)
}
}
log, audit := fetchLoggerInfo()
// Get the notification target info
notifyTarget := fetchLambdaInfo()
local := getLocalServerProperty(globalEndpoints, r)
servers := globalNotificationSys.ServerInfo()
servers = append(servers, local)
assignPoolNumbers(servers)
var backend interface{}
mode := madmin.ItemInitializing
buckets := madmin.Buckets{}
objects := madmin.Objects{}
usage := madmin.Usage{}
objectAPI := newObjectLayerFn()
if objectAPI != nil {
mode = madmin.ItemOnline
// Load data usage
dataUsageInfo, err := loadDataUsageFromBackend(ctx, objectAPI)
if err == nil {
buckets = madmin.Buckets{Count: dataUsageInfo.BucketsCount}
objects = madmin.Objects{Count: dataUsageInfo.ObjectsTotalCount}
usage = madmin.Usage{Size: dataUsageInfo.ObjectsTotalSize}
} else {
buckets = madmin.Buckets{Error: err.Error()}
objects = madmin.Objects{Error: err.Error()}
usage = madmin.Usage{Error: err.Error()}
}
// Fetching the backend information
backendInfo := objectAPI.BackendInfo()
if backendInfo.Type == madmin.Erasure {
// Calculate the number of online/offline disks of all nodes
var allDisks []madmin.Disk
for _, s := range servers {
allDisks = append(allDisks, s.Disks...)
}
onlineDisks, offlineDisks := getOnlineOfflineDisksStats(allDisks)
backend = madmin.ErasureBackend{
Type: madmin.ErasureType,
OnlineDisks: onlineDisks.Sum(),
OfflineDisks: offlineDisks.Sum(),
StandardSCParity: backendInfo.StandardSCParity,
RRSCParity: backendInfo.RRSCParity,
}
} else {
backend = madmin.FSBackend{
Type: madmin.FsType,
}
}
}
domain := globalDomainNames
services := madmin.Services{
KMS: kmsStat,
LDAP: ldap,
Logger: log,
Audit: audit,
Notifications: notifyTarget,
}
return madmin.InfoMessage{
Mode: string(mode),
Domain: domain,
Region: globalServerRegion,
SQSARN: globalNotificationSys.GetARNList(false),
DeploymentID: globalDeploymentID,
Buckets: buckets,
Objects: objects,
Usage: usage,
Services: services,
Backend: backend,
Servers: servers,
}
}
// HealthInfoHandler - GET /minio/admin/v3/healthinfo
// ----------
// Get server health info
@@ -1380,7 +1479,7 @@ func (a adminAPIHandlers) HealthInfoHandler(w http.ResponseWriter, r *http.Reque
}
query := r.URL.Query()
healthInfo := madmin.HealthInfo{}
healthInfo := madmin.HealthInfo{Version: madmin.HealthInfoVersion}
healthInfoCh := make(chan madmin.HealthInfo)
enc := json.NewEncoder(w)
@@ -1402,7 +1501,7 @@ func (a adminAPIHandlers) HealthInfoHandler(w http.ResponseWriter, r *http.Reque
logger.LogIf(ctx, enc.Encode(healthInfo))
}
deadline := 3600 * time.Second
deadline := 1 * time.Hour
if dstr := r.URL.Query().Get("deadline"); dstr != "" {
var err error
deadline, err = time.ParseDuration(dstr)
@@ -1426,86 +1525,67 @@ func (a adminAPIHandlers) HealthInfoHandler(w http.ResponseWriter, r *http.Reque
go func() {
defer close(healthInfoCh)
if cpu := query.Get("syscpu"); cpu == "true" {
cpuInfo := getLocalCPUInfo(deadlinedCtx, r)
partialWrite(healthInfo) // Write first message with only version populated
healthInfo.Sys.CPUInfo = append(healthInfo.Sys.CPUInfo, cpuInfo)
healthInfo.Sys.CPUInfo = append(healthInfo.Sys.CPUInfo, globalNotificationSys.CPUInfo(deadlinedCtx)...)
if query.Get("syscpu") == "true" {
healthInfo.Sys.CPUInfo = append(healthInfo.Sys.CPUInfo, madmin.GetCPUs(deadlinedCtx, r.Host))
healthInfo.Sys.CPUInfo = append(healthInfo.Sys.CPUInfo, globalNotificationSys.GetCPUs(deadlinedCtx)...)
partialWrite(healthInfo)
}
if diskHw := query.Get("sysdiskhw"); diskHw == "true" {
diskHwInfo := getLocalDiskHwInfo(deadlinedCtx, r)
healthInfo.Sys.DiskHwInfo = append(healthInfo.Sys.DiskHwInfo, diskHwInfo)
healthInfo.Sys.DiskHwInfo = append(healthInfo.Sys.DiskHwInfo, globalNotificationSys.DiskHwInfo(deadlinedCtx)...)
if query.Get("sysdrivehw") == "true" {
healthInfo.Sys.Partitions = append(healthInfo.Sys.Partitions, madmin.GetPartitions(deadlinedCtx, r.Host))
healthInfo.Sys.Partitions = append(healthInfo.Sys.Partitions, globalNotificationSys.GetPartitions(deadlinedCtx)...)
partialWrite(healthInfo)
}
if osInfo := query.Get("sysosinfo"); osInfo == "true" {
osInfo := getLocalOsInfo(deadlinedCtx, r)
healthInfo.Sys.OsInfo = append(healthInfo.Sys.OsInfo, osInfo)
healthInfo.Sys.OsInfo = append(healthInfo.Sys.OsInfo, globalNotificationSys.OsInfo(deadlinedCtx)...)
if query.Get("sysosinfo") == "true" {
healthInfo.Sys.OSInfo = append(healthInfo.Sys.OSInfo, madmin.GetOSInfo(deadlinedCtx, r.Host))
healthInfo.Sys.OSInfo = append(healthInfo.Sys.OSInfo, globalNotificationSys.GetOSInfo(deadlinedCtx)...)
partialWrite(healthInfo)
}
if mem := query.Get("sysmem"); mem == "true" {
memInfo := getLocalMemInfo(deadlinedCtx, r)
healthInfo.Sys.MemInfo = append(healthInfo.Sys.MemInfo, memInfo)
healthInfo.Sys.MemInfo = append(healthInfo.Sys.MemInfo, globalNotificationSys.MemInfo(deadlinedCtx)...)
if query.Get("sysmem") == "true" {
healthInfo.Sys.MemInfo = append(healthInfo.Sys.MemInfo, madmin.GetMemInfo(deadlinedCtx, r.Host))
healthInfo.Sys.MemInfo = append(healthInfo.Sys.MemInfo, globalNotificationSys.GetMemInfo(deadlinedCtx)...)
partialWrite(healthInfo)
}
if proc := query.Get("sysprocess"); proc == "true" {
procInfo := getLocalProcInfo(deadlinedCtx, r)
healthInfo.Sys.ProcInfo = append(healthInfo.Sys.ProcInfo, procInfo)
healthInfo.Sys.ProcInfo = append(healthInfo.Sys.ProcInfo, globalNotificationSys.ProcInfo(deadlinedCtx)...)
if query.Get("sysprocess") == "true" {
healthInfo.Sys.ProcInfo = append(healthInfo.Sys.ProcInfo, madmin.GetProcInfo(deadlinedCtx, r.Host))
healthInfo.Sys.ProcInfo = append(healthInfo.Sys.ProcInfo, globalNotificationSys.GetProcInfo(deadlinedCtx)...)
partialWrite(healthInfo)
}
if config := query.Get("minioconfig"); config == "true" {
cfg, err := readServerConfig(ctx, objectAPI)
logger.LogIf(ctx, err)
healthInfo.Minio.Config = cfg
partialWrite(healthInfo)
}
if drive := query.Get("perfdrive"); drive == "true" {
// Get drive perf details from local server's drive(s)
drivePerfSerial := getLocalDrives(deadlinedCtx, false, globalEndpoints, r)
drivePerfParallel := getLocalDrives(deadlinedCtx, true, globalEndpoints, r)
errStr := ""
if drivePerfSerial.Error != "" {
errStr = "serial: " + drivePerfSerial.Error
}
if drivePerfParallel.Error != "" {
errStr = errStr + " parallel: " + drivePerfParallel.Error
if query.Get("minioconfig") == "true" {
config, err := readServerConfig(ctx, objectAPI)
if err != nil {
healthInfo.Minio.Config = madmin.MinioConfig{
Error: err.Error(),
}
} else {
healthInfo.Minio.Config = madmin.MinioConfig{
Config: config,
}
}
partialWrite(healthInfo)
}
driveInfo := madmin.ServerDrivesInfo{
Addr: drivePerfSerial.Addr,
Serial: drivePerfSerial.Serial,
Parallel: drivePerfParallel.Parallel,
Error: errStr,
}
healthInfo.Perf.DriveInfo = append(healthInfo.Perf.DriveInfo, driveInfo)
if query.Get("perfdrive") == "true" {
healthInfo.Perf.Drives = append(healthInfo.Perf.Drives, getDrivePerfInfos(deadlinedCtx, r.Host))
partialWrite(healthInfo)
// Notify all other MinIO peers to report drive perf numbers
driveInfos := globalNotificationSys.DrivePerfInfoChan(deadlinedCtx)
for obd := range driveInfos {
healthInfo.Perf.DriveInfo = append(healthInfo.Perf.DriveInfo, obd)
perfCh := globalNotificationSys.GetDrivePerfInfos(deadlinedCtx)
for perfInfo := range perfCh {
healthInfo.Perf.Drives = append(healthInfo.Perf.Drives, perfInfo)
partialWrite(healthInfo)
}
partialWrite(healthInfo)
}
if net := query.Get("perfnet"); net == "true" && globalIsDistErasure {
healthInfo.Perf.Net = append(healthInfo.Perf.Net, globalNotificationSys.NetInfo(deadlinedCtx))
if globalIsDistErasure && query.Get("perfnet") == "true" {
healthInfo.Perf.Net = append(healthInfo.Perf.Net, globalNotificationSys.GetNetPerfInfo(deadlinedCtx))
partialWrite(healthInfo)
netInfos := globalNotificationSys.DispatchNetPerfChan(deadlinedCtx)
@@ -1515,10 +1595,47 @@ func (a adminAPIHandlers) HealthInfoHandler(w http.ResponseWriter, r *http.Reque
}
partialWrite(healthInfo)
healthInfo.Perf.NetParallel = globalNotificationSys.NetPerfParallelInfo(deadlinedCtx)
healthInfo.Perf.NetParallel = globalNotificationSys.GetParallelNetPerfInfo(deadlinedCtx)
partialWrite(healthInfo)
}
if query.Get("minioinfo") == "true" {
infoMessage := getServerInfo(ctx, r)
servers := []madmin.ServerInfo{}
for _, server := range infoMessage.Servers {
servers = append(servers, madmin.ServerInfo{
State: server.State,
Endpoint: server.Endpoint,
Uptime: server.Uptime,
Version: server.Version,
CommitID: server.CommitID,
Network: server.Network,
Drives: server.Disks,
PoolNumber: server.PoolNumber,
MemStats: madmin.MemStats{
Alloc: server.MemStats.Alloc,
TotalAlloc: server.MemStats.TotalAlloc,
Mallocs: server.MemStats.Mallocs,
Frees: server.MemStats.Frees,
HeapAlloc: server.MemStats.HeapAlloc,
},
})
}
healthInfo.Minio.Info = madmin.MinioInfo{
Mode: infoMessage.Mode,
Domain: infoMessage.Domain,
Region: infoMessage.Region,
SQSARN: infoMessage.SQSARN,
DeploymentID: infoMessage.DeploymentID,
Buckets: infoMessage.Buckets,
Objects: infoMessage.Objects,
Usage: infoMessage.Usage,
Services: infoMessage.Services,
Backend: infoMessage.Backend,
Servers: servers,
}
partialWrite(healthInfo)
}
}()
ticker := time.NewTicker(5 * time.Second)
@@ -1616,105 +1733,8 @@ func (a adminAPIHandlers) ServerInfoHandler(w http.ResponseWriter, r *http.Reque
return
}
kmsStat := fetchKMSStatus()
ldap := madmin.LDAP{}
if globalLDAPConfig.Enabled {
ldapConn, err := globalLDAPConfig.Connect()
if err != nil {
ldap.Status = string(madmin.ItemOffline)
} else if ldapConn == nil {
ldap.Status = "Not Configured"
} else {
// Close ldap connection to avoid leaks.
ldapConn.Close()
ldap.Status = string(madmin.ItemOnline)
}
}
log, audit := fetchLoggerInfo()
// Get the notification target info
notifyTarget := fetchLambdaInfo()
local := getLocalServerProperty(globalEndpoints, r)
servers := globalNotificationSys.ServerInfo()
servers = append(servers, local)
assignPoolNumbers(servers)
var backend interface{}
mode := madmin.ItemInitializing
buckets := madmin.Buckets{}
objects := madmin.Objects{}
usage := madmin.Usage{}
objectAPI := newObjectLayerFn()
if objectAPI != nil {
mode = madmin.ItemOnline
// Load data usage
dataUsageInfo, err := loadDataUsageFromBackend(ctx, objectAPI)
if err == nil {
buckets = madmin.Buckets{Count: dataUsageInfo.BucketsCount}
objects = madmin.Objects{Count: dataUsageInfo.ObjectsTotalCount}
usage = madmin.Usage{Size: dataUsageInfo.ObjectsTotalSize}
} else {
buckets = madmin.Buckets{Error: err.Error()}
objects = madmin.Objects{Error: err.Error()}
usage = madmin.Usage{Error: err.Error()}
}
// Fetching the backend information
backendInfo := objectAPI.BackendInfo()
if backendInfo.Type == madmin.Erasure {
// Calculate the number of online/offline disks of all nodes
var allDisks []madmin.Disk
for _, s := range servers {
allDisks = append(allDisks, s.Disks...)
}
onlineDisks, offlineDisks := getOnlineOfflineDisksStats(allDisks)
backend = madmin.ErasureBackend{
Type: madmin.ErasureType,
OnlineDisks: onlineDisks.Sum(),
OfflineDisks: offlineDisks.Sum(),
StandardSCParity: backendInfo.StandardSCParity,
RRSCParity: backendInfo.RRSCParity,
}
} else {
backend = madmin.FSBackend{
Type: madmin.FsType,
}
}
}
domain := globalDomainNames
services := madmin.Services{
KMS: kmsStat,
LDAP: ldap,
Logger: log,
Audit: audit,
Notifications: notifyTarget,
}
infoMsg := madmin.InfoMessage{
Mode: string(mode),
Domain: domain,
Region: globalServerRegion,
SQSARN: globalNotificationSys.GetARNList(false),
DeploymentID: globalDeploymentID,
Buckets: buckets,
Objects: objects,
Usage: usage,
Services: services,
Backend: backend,
Servers: servers,
}
// Marshal API response
jsonBytes, err := json.Marshal(infoMsg)
jsonBytes, err := json.Marshal(getServerInfo(ctx, r))
if err != nil {
writeErrorResponseJSON(ctx, w, toAdminAPIErr(ctx, err), r.URL)
return