Ver Fonte

Rewrites the code about SMART

Alanyeung's Windows Laptop há 4 anos atrás
pai
commit
9878fd83f6
4 ficheiros alterados com 250 adições e 246 exclusões
  1. 0 2
      disk.go
  2. 76 77
      mod/disk/smart/common.go
  3. 45 53
      mod/disk/smart/smart.go
  4. 129 114
      mod/disk/smart/structure.go

+ 0 - 2
disk.go

@@ -106,8 +106,6 @@ func DiskServiceInit() {
 				*/
 
 				adminRouter.HandleFunc("/system/disk/smart/getSMART", smartListener.GetSMART)
-				adminRouter.HandleFunc("/system/disk/smart/getSMARTTable", smartListener.CheckDiskTable)
-				adminRouter.HandleFunc("/system/disk/smart/getLogInfo", smartListener.CheckDiskTestStatus)
 			}
 		}
 

+ 76 - 77
mod/disk/smart/common.go

@@ -1,17 +1,17 @@
 package smart
 
 import (
-	"os"
-    "log"
+	"bufio"
+	"encoding/base64"
+	"errors"
+	"io/ioutil"
+	"log"
 	"net/http"
+	"os"
+	"os/exec"
 	"strconv"
 	"strings"
-	"errors"
-	"encoding/base64"
-	"bufio"
-	"io/ioutil"
 	"time"
-	"os/exec"
 )
 
 /*
@@ -49,6 +49,7 @@ func sendOK(w http.ResponseWriter) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Write([]byte("\"OK\""))
 }
+
 /*
 	The paramter move function (mv)
 
@@ -88,121 +89,119 @@ func mv(r *http.Request, getParamter string, postMode bool) (string, error) {
 }
 
 func stringInSlice(a string, list []string) bool {
-    for _, b := range list {
-        if b == a {
-            return true
-        }
-    }
-    return false
+	for _, b := range list {
+		if b == a {
+			return true
+		}
+	}
+	return false
 }
 
-
 func fileExists(filename string) bool {
-    _, err := os.Stat(filename)
-    if os.IsNotExist(err) {
-        return false
-    }
-    return true
+	_, err := os.Stat(filename)
+	if os.IsNotExist(err) {
+		return false
+	}
+	return true
 }
 
-
-func IsDir(path string) bool{
-	if (fileExists(path) == false){
+func IsDir(path string) bool {
+	if fileExists(path) == false {
 		return false
 	}
 	fi, err := os.Stat(path)
-    if err != nil {
-        log.Fatal(err)
-        return false
-    }
-    switch mode := fi.Mode(); {
-    case mode.IsDir():
-        return true
-    case mode.IsRegular():
-        return false
+	if err != nil {
+		log.Fatal(err)
+		return false
+	}
+	switch mode := fi.Mode(); {
+	case mode.IsDir():
+		return true
+	case mode.IsRegular():
+		return false
 	}
 	return false
 }
 
 func inArray(arr []string, str string) bool {
 	for _, a := range arr {
-	   if a == str {
-		  return true
-	   }
+		if a == str {
+			return true
+		}
 	}
 	return false
- }
+}
 
- func timeToString(targetTime time.Time) string{
-	 return targetTime.Format("2006-01-02 15:04:05")
- }
+func timeToString(targetTime time.Time) string {
+	return targetTime.Format("2006-01-02 15:04:05")
+}
 
- func IntToString(number int) string{
+func IntToString(number int) string {
 	return strconv.Itoa(number)
- }
+}
 
- func StringToInt(number string) (int, error){
+func StringToInt(number string) (int, error) {
 	return strconv.Atoi(number)
- }
+}
 
- func StringToInt64(number string) (int64, error){
+func StringToInt64(number string) (int64, error) {
 	i, err := strconv.ParseInt(number, 10, 64)
 	if err != nil {
 		return -1, err
 	}
 	return i, nil
- }
+}
 
- func Int64ToString(number int64) string{
-	convedNumber:=strconv.FormatInt(number,10)
+func Int64ToString(number int64) string {
+	convedNumber := strconv.FormatInt(number, 10)
 	return convedNumber
- }
+}
 
- func GetUnixTime() int64{
+func GetUnixTime() int64 {
 	return time.Now().Unix()
- }
+}
 
- func LoadImageAsBase64(filepath string) (string, error){
-	if !fileExists(filepath){
+func LoadImageAsBase64(filepath string) (string, error) {
+	if !fileExists(filepath) {
 		return "", errors.New("File not exists")
 	}
 	f, _ := os.Open(filepath)
-    reader := bufio.NewReader(f)
-    content, _ := ioutil.ReadAll(reader)
+	reader := bufio.NewReader(f)
+	content, _ := ioutil.ReadAll(reader)
 	encoded := base64.StdEncoding.EncodeToString(content)
 	return string(encoded), nil
- }
+}
 
- //Get the IP address of the current authentication user
+//Get the IP address of the current authentication user
 func ReflectUserIP(w http.ResponseWriter, r *http.Request) {
-    requestPort,_ :=  mv(r, "port", false)
-    showPort := false;
-    if (requestPort == "true"){
-        //Show port as well
-        showPort = true;
-    }
-    IPAddress := r.Header.Get("X-Real-Ip")
-    if IPAddress == "" {
-        IPAddress = r.Header.Get("X-Forwarded-For")
-    }
-    if IPAddress == "" {
-        IPAddress = r.RemoteAddr
-    }
-    if (!showPort){
-        IPAddress = IPAddress[:strings.LastIndex(IPAddress, ":")]
-
-    }
-    w.Write([]byte(IPAddress))
-    return;
+	requestPort, _ := mv(r, "port", false)
+	showPort := false
+	if requestPort == "true" {
+		//Show port as well
+		showPort = true
+	}
+	IPAddress := r.Header.Get("X-Real-Ip")
+	if IPAddress == "" {
+		IPAddress = r.Header.Get("X-Forwarded-For")
+	}
+	if IPAddress == "" {
+		IPAddress = r.RemoteAddr
+	}
+	if !showPort {
+		IPAddress = IPAddress[:strings.LastIndex(IPAddress, ":")]
+
+	}
+	w.Write([]byte(IPAddress))
+	return
 }
 
 func execCommand(executable string, args ...string) string {
 	shell := exec.Command(executable, args...) // Run command
-	output, err := shell.CombinedOutput()                     // Response from cmdline
-	if err != nil {                                             // If done w/ errors then
+	output, err := shell.CombinedOutput()      // Response from cmdline
+	if err != nil && string(output) == "" {    // If done w/ errors then
 		log.Println(err)
 		return ""
 	}
 
 	return string(output)
-}
+}

+ 45 - 53
mod/disk/smart/smart.go

@@ -14,89 +14,81 @@ import (
 	"encoding/json"
 	"log"
 	"net/http"
+	"strings"
+
 	//"os/exec"
-	"runtime"
 	"errors"
+	"runtime"
 	//"time"
 )
 
-// SMART was used for storing all Devices data
-type SMART struct {
-	Port       string       `json:"Port"`
-	DriveSmart DeviceSMART `json:"SMART"`
-}
-
-type SMARTListener struct{
+type SMARTListener struct {
 	SystemSmartExecutable string
-	DriveList DevicesList `json:"driveList"`
-	SMARTInformation []SMART `json:"smartInformation"`
+	DriveList             DevicesList `json:"driveList"`
 }
 
 // DiskSmartInit Desktop script initiation
-func NewSmartListener() (*SMARTListener, error){
+func NewSmartListener() (*SMARTListener, error) {
 	smartExec := getBinary()
 
 	log.Println("Starting SMART mointoring")
 
-	if (smartExec == "") {
-		return &SMARTListener{}, errors.New("Not supported platform")
+	if smartExec == "" {
+		return &SMARTListener{}, errors.New("not supported platform")
 	}
 
 	if !(fileExists(smartExec)) {
-		return &SMARTListener{}, errors.New("Smartctl not found")
+		return &SMARTListener{}, errors.New("smartctl not found")
 	}
 
-	driveList := scanAvailableDevices(smartExec);
-	smartInformation := readSMARTDevices(smartExec,driveList);
+	driveList := scanAvailableDevices(smartExec)
+	readSMARTDevices(smartExec, &driveList)
 
 	return &SMARTListener{
 		SystemSmartExecutable: smartExec,
-		DriveList: driveList,
-		SMARTInformation: smartInformation,
-	},nil
+		DriveList:             driveList,
+	}, nil
 }
 
-func scanAvailableDevices(smartExec string) DevicesList{
+func scanAvailableDevices(smartExec string) DevicesList {
 	rawInfo := execCommand(smartExec, "--scan", "--json=c")
-	Devices := new(DevicesList)
-	json.Unmarshal([]byte(rawInfo), &Devices)
-	return *Devices
+	devicesList := new(DevicesList)
+	json.Unmarshal([]byte(rawInfo), &devicesList)
+	//used to remove csmi devices (Intel RAID Devices)
+	numOfRemoved := 0
+	for i, device := range devicesList.Devices {
+		if strings.Contains(device.Name, "/dev/csmi") {
+			devicesList.Devices = append(devicesList.Devices[:i-numOfRemoved], devicesList.Devices[i+1-numOfRemoved:]...)
+			numOfRemoved++
+		}
+	}
+	return *devicesList
 }
 
-func readSMARTDevices(smartExec string, devicesList DevicesList) []SMART{
-	SMARTInfo := []SMART{}
-	for _, device := range devicesList.Devices {
-		rawInfo := execCommand(smartExec, "-i", device.Name, "-a", "--json=c")
-		deviceSMART := new(SMART)
+func readSMARTDevices(smartExec string, devicesList *DevicesList) {
+	for i, device := range devicesList.Devices {
+		rawInfo := execCommand(smartExec, device.Name, "--info", "--all", "--json=c")
+		deviceSMART := new(DeviceSMART)
 		json.Unmarshal([]byte(rawInfo), &deviceSMART)
-		SMARTInfo = append(SMARTInfo, *deviceSMART)
+		devicesList.Devices[i].Smart = *deviceSMART
 	}
-	return SMARTInfo
 }
 
-
-func (s *SMARTListener)CheckDiskTable(w http.ResponseWriter, r *http.Request) {
-	sendJSONResponse(w, string(""))
-}
-
-func (s *SMARTListener)CheckDiskTestStatus(w http.ResponseWriter, r *http.Request) {
-	sendJSONResponse(w, string(""))
+func (s *SMARTListener) GetSMART(w http.ResponseWriter, r *http.Request) {
+	jsonText, _ := json.Marshal(s.DriveList)
+	sendJSONResponse(w, string(jsonText))
 }
 
-func (s *SMARTListener)GetSMART(w http.ResponseWriter, r *http.Request) {
-	sendJSONResponse(w, string(""))
+func getBinary() string {
+	if runtime.GOOS == "windows" {
+		return ".\\system\\disk\\smart\\win\\smartctl.exe"
+	} else if runtime.GOOS == "linux" {
+		if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
+			return "./system/disk/smart/linux/smartctl_armv6"
+		}
+		if runtime.GOARCH == "386" || runtime.GOARCH == "amd64" {
+			return "./system/disk/smart/linux/smartctl_i386"
+		}
+	}
+	return ""
 }
-
-func getBinary() string{
-    if runtime.GOOS == "windows" {
-        return "./system/disk/smart/win/smartctl.exe"
-    } else if runtime.GOOS == "linux" {
-        if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
-            return "./system/disk/smart/linux/smartctl_armv6"
-        }
-        if runtime.GOARCH == "386" || runtime.GOARCH == "amd64"{
-            return "./system/disk/smart/linux/smartctl_i386"
-        }
-    }
-    return ""
-}

+ 129 - 114
mod/disk/smart/structure.go

@@ -2,56 +2,65 @@ package smart
 
 // DevicesList was used for storing the disk scanning result
 type DevicesList struct {
-	JSONFormatVersion []int `json:"json_format_version"`
-	Smartctl          struct {
-		Version      []int    `json:"version"`
-		SvnRevision  string   `json:"svn_revision"`
-		PlatformInfo string   `json:"platform_info"`
-		BuildInfo    string   `json:"build_info"`
-		Argv         []string `json:"argv"`
-		Messages     []struct {
-			String   string `json:"string"`
-			Severity string `json:"severity"`
-		} `json:"messages"`
-		ExitStatus int `json:"exit_status"`
-	} `json:"smartctl"`
+	/*
+		JSONFormatVersion []int `json:"json_format_version"`
+			Smartctl          struct {
+				Version      []int    `json:"version"`
+				SvnRevision  string   `json:"svn_revision"`
+				PlatformInfo string   `json:"platform_info"`
+				BuildInfo    string   `json:"build_info"`
+				Argv         []string `json:"argv"`
+				Messages     []struct {
+					String   string `json:"string"`
+					Severity string `json:"severity"`
+				} `json:"messages"`
+				ExitStatus int `json:"exit_status"`
+			} `json:"smartctl"`
+	*/
 	Devices []struct {
-		Name     string `json:"name"`
-		InfoName string `json:"info_name"`
-		Type     string `json:"type"`
-		Protocol string `json:"protocol"`
+		Name     string      `json:"name"`
+		InfoName string      `json:"info_name"`
+		Type     string      `json:"type"`
+		Protocol string      `json:"protocol"`
+		Smart    DeviceSMART `json:"smart"`
 	} `json:"devices"`
 }
 
 // DeviceSMART was used for storing each disk smart information
 type DeviceSMART struct {
-	JSONFormatVersion []int `json:"json_format_version"`
-	Smartctl          struct {
-		Version      []int    `json:"version"`
-		SvnRevision  string   `json:"svn_revision"`
-		PlatformInfo string   `json:"platform_info"`
-		BuildInfo    string   `json:"build_info"`
-		Argv         []string `json:"argv"`
-		Messages     []struct {
-			String   string `json:"string"`
-			Severity string `json:"severity"`
-		} `json:"messages"`
-		ExitStatus int `json:"exit_status"`
-	} `json:"smartctl"`
-	Device struct {
-		Name     string `json:"name"`
-		InfoName string `json:"info_name"`
-		Type     string `json:"type"`
-		Protocol string `json:"protocol"`
-	} `json:"device"`
+	/*
+		JSONFormatVersion []int `json:"json_format_version"`
+			Smartctl          struct {
+				Version      []int    `json:"version"`
+				SvnRevision  string   `json:"svn_revision"`
+				PlatformInfo string   `json:"platform_info"`
+				BuildInfo    string   `json:"build_info"`
+				Argv         []string `json:"argv"`
+				Messages     []struct {
+					String   string `json:"string"`
+					Severity string `json:"severity"`
+				} `json:"messages"`
+				ExitStatus int `json:"exit_status"`
+			} `json:"smartctl"`
+	*/
+	/*
+		Device struct {
+			Name     string `json:"name"`
+			InfoName string `json:"info_name"`
+			Type     string `json:"type"`
+			Protocol string `json:"protocol"`
+		} `json:"device"`
+	*/
 	ModelFamily  string `json:"model_family"`
 	ModelName    string `json:"model_name"`
 	SerialNumber string `json:"serial_number"`
-	Wwn          struct {
-		Naa int   `json:"naa"`
-		Oui int   `json:"oui"`
-		ID  int64 `json:"id"`
-	} `json:"wwn"`
+	/*
+		Wwn          struct {
+			Naa int   `json:"naa"`
+			Oui int   `json:"oui"`
+			ID  int64 `json:"id"`
+		} `json:"wwn"`
+	*/
 	FirmwareVersion string `json:"firmware_version"`
 	UserCapacity    struct {
 		Blocks int   `json:"blocks"`
@@ -84,52 +93,56 @@ type DeviceSMART struct {
 			BitsPerUnit    int    `json:"bits_per_unit"`
 		} `json:"current"`
 	} `json:"interface_speed"`
-	LocalTime struct {
-		TimeT   int    `json:"time_t"`
-		Asctime string `json:"asctime"`
-	} `json:"local_time"`
+	/*
+		LocalTime struct {
+			TimeT   int    `json:"time_t"`
+			Asctime string `json:"asctime"`
+		} `json:"local_time"`
+	*/
 	SmartStatus struct {
 		Passed bool `json:"passed"`
 	} `json:"smart_status"`
-	AtaSmartData struct {
-		OfflineDataCollection struct {
-			Status struct {
-				Value  int    `json:"value"`
-				String string `json:"string"`
-			} `json:"status"`
-			CompletionSeconds int `json:"completion_seconds"`
-		} `json:"offline_data_collection"`
-		SelfTest struct {
-			Status struct {
-				Value  int    `json:"value"`
-				String string `json:"string"`
-				Passed bool   `json:"passed"`
-			} `json:"status"`
-			PollingMinutes struct {
-				Short      int `json:"short"`
-				Extended   int `json:"extended"`
-				Conveyance int `json:"conveyance"`
-			} `json:"polling_minutes"`
-		} `json:"self_test"`
-		Capabilities struct {
-			Values                        []int `json:"values"`
-			ExecOfflineImmediateSupported bool  `json:"exec_offline_immediate_supported"`
-			OfflineIsAbortedUponNewCmd    bool  `json:"offline_is_aborted_upon_new_cmd"`
-			OfflineSurfaceScanSupported   bool  `json:"offline_surface_scan_supported"`
-			SelfTestsSupported            bool  `json:"self_tests_supported"`
-			ConveyanceSelfTestSupported   bool  `json:"conveyance_self_test_supported"`
-			SelectiveSelfTestSupported    bool  `json:"selective_self_test_supported"`
-			AttributeAutosaveEnabled      bool  `json:"attribute_autosave_enabled"`
-			ErrorLoggingSupported         bool  `json:"error_logging_supported"`
-			GpLoggingSupported            bool  `json:"gp_logging_supported"`
-		} `json:"capabilities"`
-	} `json:"ata_smart_data"`
-	AtaSctCapabilities struct {
-		Value                         int  `json:"value"`
-		ErrorRecoveryControlSupported bool `json:"error_recovery_control_supported"`
-		FeatureControlSupported       bool `json:"feature_control_supported"`
-		DataTableSupported            bool `json:"data_table_supported"`
-	} `json:"ata_sct_capabilities"`
+	/*
+			AtaSmartData struct {
+				OfflineDataCollection struct {
+					Status struct {
+						Value  int    `json:"value"`
+						String string `json:"string"`
+					} `json:"status"`
+					CompletionSeconds int `json:"completion_seconds"`
+				} `json:"offline_data_collection"`
+				SelfTest struct {
+					Status struct {
+						Value  int    `json:"value"`
+						String string `json:"string"`
+						Passed bool   `json:"passed"`
+					} `json:"status"`
+					PollingMinutes struct {
+						Short      int `json:"short"`
+						Extended   int `json:"extended"`
+						Conveyance int `json:"conveyance"`
+					} `json:"polling_minutes"`
+				} `json:"self_test"`
+				Capabilities struct {
+					Values                        []int `json:"values"`
+					ExecOfflineImmediateSupported bool  `json:"exec_offline_immediate_supported"`
+					OfflineIsAbortedUponNewCmd    bool  `json:"offline_is_aborted_upon_new_cmd"`
+					OfflineSurfaceScanSupported   bool  `json:"offline_surface_scan_supported"`
+					SelfTestsSupported            bool  `json:"self_tests_supported"`
+					ConveyanceSelfTestSupported   bool  `json:"conveyance_self_test_supported"`
+					SelectiveSelfTestSupported    bool  `json:"selective_self_test_supported"`
+					AttributeAutosaveEnabled      bool  `json:"attribute_autosave_enabled"`
+					ErrorLoggingSupported         bool  `json:"error_logging_supported"`
+					GpLoggingSupported            bool  `json:"gp_logging_supported"`
+				} `json:"capabilities"`
+			} `json:"ata_smart_data"`
+		AtaSctCapabilities struct {
+			Value                         int  `json:"value"`
+			ErrorRecoveryControlSupported bool `json:"error_recovery_control_supported"`
+			FeatureControlSupported       bool `json:"feature_control_supported"`
+			DataTableSupported            bool `json:"data_table_supported"`
+		} `json:"ata_sct_capabilities"`
+	*/
 	AtaSmartAttributes struct {
 		Revision int `json:"revision"`
 		Table    []struct {
@@ -163,40 +176,42 @@ type DeviceSMART struct {
 	Temperature     struct {
 		Current int `json:"current"`
 	} `json:"temperature"`
-	AtaSmartSelfTestLog struct {
-		Standard struct {
+	/*
+			AtaSmartSelfTestLog struct {
+				Standard struct {
+					Revision int `json:"revision"`
+					Table    []struct {
+						Type struct {
+							Value  int    `json:"value"`
+							String string `json:"string"`
+						} `json:"type"`
+						Status struct {
+							Value  int    `json:"value"`
+							String string `json:"string"`
+							Passed bool   `json:"passed"`
+						} `json:"status,omitempty"`
+						LifetimeHours int `json:"lifetime_hours"`
+					} `json:"table"`
+					Count              int `json:"count"`
+					ErrorCountTotal    int `json:"error_count_total"`
+					ErrorCountOutdated int `json:"error_count_outdated"`
+				} `json:"standard"`
+			} `json:"ata_smart_self_test_log"`
+		AtaSmartSelectiveSelfTestLog struct {
 			Revision int `json:"revision"`
 			Table    []struct {
-				Type struct {
-					Value  int    `json:"value"`
-					String string `json:"string"`
-				} `json:"type"`
+				LbaMin int `json:"lba_min"`
+				LbaMax int `json:"lba_max"`
 				Status struct {
 					Value  int    `json:"value"`
 					String string `json:"string"`
-					Passed bool   `json:"passed"`
-				} `json:"status,omitempty"`
-				LifetimeHours int `json:"lifetime_hours"`
+				} `json:"status"`
 			} `json:"table"`
-			Count              int `json:"count"`
-			ErrorCountTotal    int `json:"error_count_total"`
-			ErrorCountOutdated int `json:"error_count_outdated"`
-		} `json:"standard"`
-	} `json:"ata_smart_self_test_log"`
-	AtaSmartSelectiveSelfTestLog struct {
-		Revision int `json:"revision"`
-		Table    []struct {
-			LbaMin int `json:"lba_min"`
-			LbaMax int `json:"lba_max"`
-			Status struct {
-				Value  int    `json:"value"`
-				String string `json:"string"`
-			} `json:"status"`
-		} `json:"table"`
-		Flags struct {
-			Value                int  `json:"value"`
-			RemainderScanEnabled bool `json:"remainder_scan_enabled"`
-		} `json:"flags"`
-		PowerUpScanResumeMinutes int `json:"power_up_scan_resume_minutes"`
-	} `json:"ata_smart_selective_self_test_log"`
+			Flags struct {
+				Value                int  `json:"value"`
+				RemainderScanEnabled bool `json:"remainder_scan_enabled"`
+			} `json:"flags"`
+			PowerUpScanResumeMinutes int `json:"power_up_scan_resume_minutes"`
+		} `json:"ata_smart_selective_self_test_log"`
+	*/
 }