123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- package smart
- /*
- DISK SMART Service Listener
- Original author: alanyeung
- Rewritten by tobychui in Oct 2020 for system arch upgrade
- This module is not the core part of aroz online system.
- If you want to remove disk smart handler (e.g. running in VM?)
- remove the corrisponding code in disk.go
- */
- import (
- "encoding/json"
- "log"
- "net/http"
- "os/exec"
- "runtime"
- "errors"
- "time"
- )
- // SMART was used for storing all Devices data
- type SMART struct {
- Port string `json:"Port"`
- DriveSmart *DeviceSMART `json:"SMART"`
- }
- type SMARTListener struct{
- SystemSmartExecutable string
- LastScanTime int64
- SMARTInformation []*SMART
- ReadingInProgress bool
- }
- // DiskSmartInit Desktop script initiation
- func NewSmartListener() (*SMARTListener, error){
- var SystemSmartExecutable string = ""
- log.Println("Starting SMART mointoring")
- if !(fileExists("system/disk/smart/win/smartctl.exe") || fileExists("system/disk/smart/linux/smartctl_arm") || fileExists("system/disk/smart/linux/smartctl_arm64") || fileExists("system/disk/smart/linux/smartctl_i386")) {
- return &SMARTListener{}, errors.New("Smartctl.exe not found")
- }
- if runtime.GOOS == "windows" {
- SystemSmartExecutable = "./system/disk/smart/win/smartctl.exe"
- } else if runtime.GOOS == "linux" {
- if runtime.GOARCH == "arm" {
- SystemSmartExecutable = "./system/disk/smart/linux/smartctl_armv6"
- }
- if runtime.GOARCH == "arm64" {
- SystemSmartExecutable = "./system/disk/smart/linux/smartctl_armv6"
- }
- if runtime.GOARCH == "386" {
- SystemSmartExecutable = "./system/disk/smart/linux/smartctl_i386"
- }
- if runtime.GOARCH == "amd64" {
- SystemSmartExecutable = "./system/disk/smart/linux/smartctl_i386"
- }
- } else {
- return &SMARTListener{}, errors.New("Not supported platform")
- }
- return &SMARTListener{
- SystemSmartExecutable: SystemSmartExecutable,
- LastScanTime: 0,
- SMARTInformation: []*SMART{},
- ReadingInProgress: false,
- },nil
- }
- // ReadSMART xxx
- func (s *SMARTListener)ReadSMART() []*SMART {
- if time.Now().Unix()-s.LastScanTime > 30 {
- if (s.ReadingInProgress == false){
- //Set reading flag to true
- s.ReadingInProgress = true;
- s.SMARTInformation = []*SMART{}
- //Scan disk
- cmd := exec.Command(s.SystemSmartExecutable, "--scan", "--json=c")
- out, _ := cmd.CombinedOutput()
- Devices := new(DevicesList)
- DevicesOutput := string(out)
- json.Unmarshal([]byte(DevicesOutput), &Devices)
- for _, element := range Devices.Devices {
- //Load SMART for each drive
- cmd := exec.Command(s.SystemSmartExecutable, "-i", element.Name, "-a", "--json=c")
- out, err := cmd.CombinedOutput()
- if err != nil{
- //log.Println(string(out), err);
- }
- InvSMARTInformation := new(DeviceSMART)
- SMARTOutput := string(out)
- json.Unmarshal([]byte(SMARTOutput), &InvSMARTInformation)
- if len(InvSMARTInformation.Smartctl.Messages) > 0 {
- if InvSMARTInformation.Smartctl.Messages[0].Severity == "error" {
- log.Println("[SMART Mointoring] Disk " + element.Name + " cannot be readed")
- } else {
- //putting everything into that struct array
- n := SMART{Port: element.Name, DriveSmart: InvSMARTInformation}
- s.SMARTInformation = append(s.SMARTInformation, &n)
- }
- } else {
- //putting everything into that struct array
- n := SMART{Port: element.Name, DriveSmart: InvSMARTInformation}
- s.SMARTInformation = append(s.SMARTInformation, &n)
- }
- }
- s.LastScanTime = time.Now().Unix()
- //Set reading flag to false
- s.ReadingInProgress = false;
- }
- }
- return s.SMARTInformation
- }
- func (s *SMARTListener)GetSMART(w http.ResponseWriter, r *http.Request) {
- jsonText, _ := json.Marshal(s.ReadSMART())
- sendJSONResponse(w, string(jsonText))
- }
- func (s *SMARTListener)CheckDiskTable(w http.ResponseWriter, r *http.Request) {
- disks, ok := r.URL.Query()["disk"]
- if !ok || len(disks[0]) < 1 {
- log.Println("Parameter DISK not found.")
- return
- }
- DiskStatus := new(DeviceSMART)
- for _, info := range s.ReadSMART() {
- if info.Port == disks[0] {
- DiskStatus = info.DriveSmart
- }
- }
- JSONStr, _ := json.Marshal(DiskStatus.AtaSmartAttributes.Table)
- //send!
- sendJSONResponse(w, string(JSONStr))
- }
- func (s *SMARTListener)CheckDiskTestStatus(w http.ResponseWriter, r *http.Request) {
- disks, ok := r.URL.Query()["disk"]
- if !ok || len(disks[0]) < 1 {
- log.Println("Parameter DISK not found.")
- return
- }
- DiskTestStatus := new(DeviceSMART)
- for _, info := range s.ReadSMART() {
- if info.Port == disks[0] {
- DiskTestStatus = info.DriveSmart
- }
- }
- JSONStr, _ := json.Marshal(DiskTestStatus.AtaSmartData.SelfTest.Status)
- //send!
- sendJSONResponse(w, string(JSONStr))
- }
|