Эх сурвалжийг харах

Merge branch 'master' of yeungalan/arozos into master

I have no idea what you have changed but seems no problem so I will just merge it
TC 4 жил өмнө
parent
commit
561353031d

+ 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)
 			}
 		}
 

+ 3 - 3
go.mod

@@ -5,6 +5,7 @@ go 1.13
 require (
 	github.com/andybalholm/brotli v1.0.0 // indirect
 	github.com/boltdb/bolt v1.3.1
+	github.com/brutella/hc v1.2.4
 	github.com/dhowden/tag v0.0.0-20200828214007-46e57f75dbfc
 	github.com/disintegration/imaging v1.6.2
 	github.com/fclairamb/ftpserverlib v0.8.0
@@ -38,9 +39,8 @@ require (
 	github.com/valyala/fasttemplate v1.1.0
 	gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect
 	gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3
-	golang.org/x/net v0.0.0-20200301022130-244492dfa37a
-	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
-	golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
+	golang.org/x/net v0.0.0-20210119194325-5f4716e94777
+	golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
 	golang.org/x/text v0.3.3 // indirect
 	gopkg.in/sourcemap.v1 v1.0.5 // indirect
 )

+ 22 - 0
go.sum

@@ -36,6 +36,10 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
 github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
 github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
 github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
+github.com/brutella/dnssd v1.2.0 h1:bgrSycmZ2+u4BoJxRf1BzSlnViSAfeXWVdujqjLA004=
+github.com/brutella/dnssd v1.2.0/go.mod h1:FpJqlQ8+XU6w1vbnG1zJiQPTRE5fvQIRdrcBojMVuuQ=
+github.com/brutella/hc v1.2.4 h1:dQjLi4bjUbKG4436N7WXH6W7iHQgfnCceE9DxyOuSnA=
+github.com/brutella/hc v1.2.4/go.mod h1:TPPdombm3gA/2fsSON6ct2km7z7Vi8lQNqE+fzuDHQM=
 github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
 github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
 github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
@@ -232,6 +236,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
 github.com/mholt/archiver/v3 v3.3.0 h1:vWjhY8SQp5yzM9P6OJ/eZEkmi3UAbRrxCq48MxjAzig=
 github.com/mholt/archiver/v3 v3.3.0/go.mod h1:YnQtqsp+94Rwd0D/rk5cnLrxusUBUXg+08Ebtr1Mqao=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
 github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
 github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg=
@@ -365,6 +371,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/tadglines/go-pkgs v0.0.0-20140924210655-1f86682992f1 h1:ms/IQpkxq+t7hWpgKqCE5KjAUQWC24mqBrnL566SWgE=
+github.com/tadglines/go-pkgs v0.0.0-20140924210655-1f86682992f1/go.mod h1:roo6cZ/uqpwKMuvPG0YmzI5+AmUiMWfjCBZpGXqbTxE=
 github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
 github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -382,6 +390,8 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70
 github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
+github.com/xiam/to v0.0.0-20191116183551-8328998fc0ed h1:Gjnw8buhv4V8qXaHtAWPnKXNpCNx62heQpjO8lOY0/M=
+github.com/xiam/to v0.0.0-20191116183551-8328998fc0ed/go.mod h1:cqbG7phSzrbdg3aj+Kn63bpVruzwDZi58CpxlZkjwzw=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 h1:dizWJqTWjwyD8KGcMOwgrkqu1JIkofYgKkmDeNE7oAs=
 gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40/go.mod h1:rOnSnoRyxMI3fe/7KIbVcsHRGxe30OONv8dEgo+vCfA=
@@ -410,6 +420,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
+golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
@@ -442,6 +454,8 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCT
 golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -452,6 +466,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -468,10 +484,16 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=

+ 1 - 1
iot.go

@@ -97,4 +97,4 @@ func IoTHubInit() {
 
 	}
 
-}
+}

+ 85 - 74
mod/disk/smart/common.go

@@ -1,15 +1,16 @@
 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"
 )
 
@@ -48,6 +49,7 @@ func sendOK(w http.ResponseWriter) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Write([]byte("\"OK\""))
 }
+
 /*
 	The paramter move function (mv)
 
@@ -87,110 +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 && string(output) == "" {    // If done w/ errors then
+		log.Println(err)
+		return ""
+	}
+
+	return string(output)
+}

+ 72 - 112
mod/disk/smart/smart.go

@@ -14,143 +14,103 @@ import (
 	"encoding/json"
 	"log"
 	"net/http"
-	"os/exec"
-	"runtime"
+	"strings"
+
+	//"os/exec"
 	"errors"
-	"time"
+	"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
-	LastScanTime int64
-	SMARTInformation []*SMART
-	ReadingInProgress bool
+	DriveList             DevicesList `json:"driveList"`
 }
 
 // DiskSmartInit Desktop script initiation
-func NewSmartListener() (*SMARTListener, error){
-	var SystemSmartExecutable string = ""
+func NewSmartListener() (*SMARTListener, error) {
+	smartExec := getBinary()
 
 	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 smartExec == "" {
+		return &SMARTListener{}, errors.New("not supported platform")
 	}
-	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")
+
+	if !(fileExists(smartExec)) {
+		return &SMARTListener{}, errors.New("smartctl not found")
 	}
+
+	driveList := scanAvailableDevices(smartExec)
+	readSMARTDevices(smartExec, &driveList)
+	fillHealthyStatus(&driveList)
 	return &SMARTListener{
-		SystemSmartExecutable: SystemSmartExecutable,
-		LastScanTime: 0,
-		SMARTInformation: []*SMART{},
-		ReadingInProgress: false,
-	},nil
+		SystemSmartExecutable: smartExec,
+		DriveList:             driveList,
+	}, 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;
+func scanAvailableDevices(smartExec string) DevicesList {
+	rawInfo := execCommand(smartExec, "--scan", "--json=c")
+	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 s.SMARTInformation
+	return *devicesList
 }
 
-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
+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)
+		devicesList.Devices[i].Smart = *deviceSMART
 	}
+}
 
-	DiskStatus := new(DeviceSMART)
-	for _, info := range s.ReadSMART() {
-		if info.Port == disks[0] {
-			DiskStatus = info.DriveSmart
+func fillHealthyStatus(devicesList *DevicesList) {
+	devicesList.Healthy = "Normal"
+	for i, device := range devicesList.Devices {
+		for j, smartTableElement := range device.Smart.AtaSmartAttributes.Table {
+			devicesList.Devices[i].Smart.Healthy = "Normal"
+			devicesList.Devices[i].Smart.AtaSmartAttributes.Table[j].Healthy = "Normal"
+			if smartTableElement.WhenFailed == "FAILING_NOW" {
+				devicesList.Devices[i].Smart.AtaSmartAttributes.Table[j].Healthy = "Failing"
+				devicesList.Devices[i].Smart.Healthy = "Failing"
+				devicesList.Healthy = "Failing"
+				break
+			}
+			if smartTableElement.WhenFailed == "In_the_past" {
+				devicesList.Devices[i].Smart.AtaSmartAttributes.Table[j].Healthy = "Attention"
+				devicesList.Devices[i].Smart.Healthy = "Attention"
+				devicesList.Healthy = "Attention"
+				break
+			}
 		}
 	}
-	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
-	}
+func (s *SMARTListener) GetSMART(w http.ResponseWriter, r *http.Request) {
+	jsonText, _ := json.Marshal(s.DriveList)
+	sendJSONResponse(w, string(jsonText))
+}
 
-	DiskTestStatus := new(DeviceSMART)
-	for _, info := range s.ReadSMART() {
-		if info.Port == disks[0] {
-			DiskTestStatus = info.DriveSmart
+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"
 		}
 	}
-	JSONStr, _ := json.Marshal(DiskTestStatus.AtaSmartData.SelfTest.Status)
-	//send!
-	sendJSONResponse(w, string(JSONStr))
+	return ""
 }

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

@@ -2,56 +2,66 @@ 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"`
+	Healthy string `json:"healthy"`
 }
 
 // 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 +94,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 {
@@ -139,6 +153,7 @@ type DeviceSMART struct {
 			Worst      int    `json:"worst"`
 			Thresh     int    `json:"thresh"`
 			WhenFailed string `json:"when_failed"`
+			Healthy    string `json:"healthy"`
 			Flags      struct {
 				Value         int    `json:"value"`
 				String        string `json:"string"`
@@ -163,40 +178,43 @@ 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"`
+	*/
+	Healthy string `json:"healthy"`
 }

+ 0 - 62
web/SystemAO/disk/smart/dotest.html

@@ -1,62 +0,0 @@
-<!DOCTYPE html>
-<meta name="apple-mobile-web-app-capable" content="yes" />
-<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=0.6, maximum-scale=0.6" />
-<html>
-
-<head>
-    <meta charset="UTF-8">
-    <script type='text/javascript' charset='utf-8'>
-        // Hides mobile browser's address bar when page is done loading.
-        window.addEventListener('load', function(e) {
-            setTimeout(function() {
-                window.scrollTo(0, 1);
-            }, 1);
-        }, false);
-    </script>
-    <title>ArOZ Onlineβ</title>
-    <link rel="stylesheet" href="../../../script/tocas/tocas.css">
-    <script src="../../../script/tocas/tocas.js"></script>
-    <script src="../../../script/jquery.min.js"></script>
-    <!--<script src="../../../script/ao_module.js"></script>-->
-</head>
-
-<body style="background-color: rgba(255, 255, 255,0.9)">
-    <br>
-    <div class="ts container">
-        <p id="Tstatus">Quick diagnostic in progress... Approximate time was 3 minutes.</p>
-        <div class="ts progress">
-            <div class="bar" id="prbar" style="width: 0%"></div>
-        </div>
-        <p id="status"></p>
-    </div>
-    <script>
-        var timer = setInterval(function() {
-            $.getJSON("../../../system/disk/smart/getLogInfo?disk=" + get("disk"), function(data) {
-                if (data["value"] == 246) {
-                    var width = data["remaining_percent"];
-                    $("#prbar").attr("style", "width: " + (100 - width) + "%");
-                    $("#status").text("Status:" + data["string"]);
-                } else if (data["value"] == 16) {
-                    $("#Tstatus").text("Harddisk test aborted.");
-                    $("#status").text("Status:" + data["string"]);
-                } else if (data["value"] == 0) {
-                    $("#Tstatus").text("Harddisk test finished.");
-                    $("#prbar").attr("style", "width: 100%");
-                    $("#status").text("Status:" + data["string"]);
-                }
-            });
-        }, 3000);
-
-        //https://stackoverflow.com/questions/831030/how-to-get-get-request-parameters-in-javascript
-        function get(name) {
-            if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search)) {
-                return decodeURIComponent(name[1]);
-            }
-        }
-    </script>
-</body>
-
-</html>
-<?php
-exec('sudo smartctl -t short -C '.$_GET["disk"]);
-?>

+ 1 - 0
web/SystemAO/disk/smart/img/hard-drive.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-hard-drive"><line x1="22" y1="12" x2="2" y2="12"></line><path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path><line x1="6" y1="16" x2="6.01" y2="16"></line><line x1="10" y1="16" x2="10.01" y2="16"></line></svg>

+ 0 - 114
web/SystemAO/disk/smart/log.html

@@ -1,114 +0,0 @@
-<!DOCTYPE html>
-<meta name="apple-mobile-web-app-capable" content="yes" />
-<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=0.6, maximum-scale=0.6" />
-<html>
-
-<head>
-    <meta charset="UTF-8">
-    <script type='text/javascript' charset='utf-8'>
-        // Hides mobile browser's address bar when page is done loading.
-        window.addEventListener('load', function(e) {
-            setTimeout(function() {
-                window.scrollTo(0, 1);
-            }, 1);
-        }, false);
-    </script>
-    <title>ArOZ Onlineβ</title>
-    <link rel="stylesheet" href="../../../script/tocas/tocas.css">
-    <script src="../../../script/tocas/tocas.js"></script>
-    <script src="../../../script/jquery.min.js"></script>
-    <!--<script src="../../../script/ao_module.js"></script>-->
-    <style>
-
-    </style>
-</head>
-
-<body style="background-color: rgba(255, 255, 255,0.9)">
-    <table class="ts celled striped table">
-        <thead>
-            <tr>
-                <th>Disk</th>
-                <th>Serial Number</th>
-                <th>Position</th>
-                <th>Event</th>
-            </tr>
-        </thead>
-        <tbody id="log_result">
-        </tbody>
-    </table>
-    <div>
-    </div>
-
-    <!-- use for displaying dialog , for VDI user , use VDI module instead -->
-    <div class="ts modals dimmer">
-        <dialog id="modal" class="ts basic modal" style="background-color: white;color: black!important" open>
-            <div class="content" id="modaldata">
-            </div>
-            <div class="actions">
-                <div class="ts fluid separated stackable buttons">
-                    <button class="ts info button">Close</button>
-                </div>
-            </div>
-    </div>
-
-    <div id="msgbox" class="ts bottom right snackbar">
-        <div class="content">
-            Your request is processing now.
-        </div>
-    </div>
-
-    <br><br>
-    <script>
-        $.getJSON("../../system/disk/smart/getSMART", function(data) {
-            if ($(data).length == 0) {
-                msg("No harddisk detected.");
-                LogHTML = "";
-                LogHTML += "<tr>"
-                LogHTML += "<td><i class=\"big caution sign icon\"></i>No log was founded on this server.</td>"
-                LogHTML += "</tr>"
-                $("#log_result").append(LogHTML);
-            }
-            $.each(data, function(id, disk) {
-                if (disk.SMART.ata_smart_self_test_log.standard.table == null) {
-                    msg("No LOG available");
-                }
-                LogHTML = "";
-                $.each(disk.SMART.ata_smart_self_test_log.standard.table, function(index, value) {
-                    LogHTML += "<tr>"
-                    LogHTML += "<td class=\"collapsing\">" + disk.SMART.ModelName + "</td>"
-                    LogHTML += "<td>" + disk.SMART.SerialNumber + "</td>"
-                    LogHTML += "<td>" + disk.Port + "</td>"
-                    LogHTML += "<td>" + value.Type.String + " - " + value.Status.String + "</td>"
-                    LogHTML += "</tr>"
-                });
-                $("#log_result").append(LogHTML);
-            });
-        });
-
-        function msg(content) {
-            ts('.snackbar').snackbar({
-                content: content,
-                actionEmphasis: 'negative',
-            });
-        }
-
-
-        function showDialog(href, x, y) {
-            $("#modaldata").html("");
-            if (loadViaSystemSetting !== undefined && loadViaSystemSetting == true) {
-                href = "../disk/smart/" + href;
-            }
-            $("#modaldata").load(href);
-            ts('#modal').modal({
-                approve: '.info',
-                onApprove: function() {
-                    try {
-                        clearInterval(timer);
-                    } catch (err) {}
-                }
-            }).modal("show")
-        }
-    </script>
-</body>
-
-</html>

+ 106 - 226
web/SystemAO/disk/smart/smart.html

@@ -1,215 +1,92 @@
-<!DOCTYPE html>
-<meta name="apple-mobile-web-app-capable" content="yes" />
-<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=0.6, maximum-scale=0.6" />
-<html>
-
-<head>
-    <meta charset="UTF-8">
-    <script type='text/javascript' charset='utf-8'>
-        // Hides mobile browser's address bar when page is done loading.
-        window.addEventListener('load', function(e) {
-            setTimeout(function() {
-                window.scrollTo(0, 1);
-            }, 1);
-        }, false);
-    </script>
-    <title>ArOZ Onlineβ</title>
-    <link rel="stylesheet" href="../../../script/tocas/tocas.css">
-    <script src="../../../script/tocas/tocas.js"></script>
-    <script src="../../../script/jquery.min.js"></script>
-    <!--<script src="../../../script/ao_module.js"></script>-->
-    <style>
-
-    </style>
-</head>
-
-<body style="background-color: rgba(255, 255, 255,0.9)">
-    <div class="ts relaxed separated mini compact buttons">
-        <button onclick="showSMART(this)" class="ts button">Health Info</button>
-        <button onclick="shortTest(this)" class="ts button">S.M.A.R.T Test</button>
-    </div>
-    <div class="ts divider"></div>
-    <div class="ts bottom attached vertical menu" id="mainmenu">
-    </div>
-
-
-
-
-
-
-
-    <div id="mainmenumsg" style="display:none;">
-        <p>Location: <span id="location"></span></p>
-        <p>Temperature: <span id="temperature"></span></p>
-        <p>Serial Number: <span id="serial_number"></span></p>
-        <p>Firmware Version: <span id="firmware_version"></span></p>
-        <p>SMART Support: <span id="smart"></span></p>
-    </div>
-
-    <div>
-    </div>
 
-    <!-- use for displaying dialog , for VDI user , use VDI module instead -->
-    <div class="ts modals dimmer">
-        <dialog id="modal" class="ts basic modal" style="background-color: white;color: black!important" open>
-            <div class="content" id="modaldata">
-            </div>
-            <div class="actions">
-                <div class="ts fluid separated stackable buttons">
-                    <button class="ts info button">Close</button>
-                </div>
+<html>
+    <head>
+        <title>Disk Quota</title>
+        <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
+        <link rel="stylesheet" href="../../../script/semantic/semantic.min.css">
+        <link rel="stylesheet" href="../disk/quota/script/Chart.min.css">
+        <script type="text/javascript" src="../../../script/jquery.min.js"></script>
+        <script type="text/javascript" src="../../../script/semantic/semantic.min.js"></script>
+        <script src="../disk/quota/script/Chart.min.js"></script>
+        <style>
+
+        </style>
+    </head>
+    <body>
+        <div class="ui container">
+            <p>Drive SMART</p>
+            <h1 class="ui header">
+                <span id="healthy">Loading</span>
+                <div class="sub header"><span id="totaldisk">N/A</span> disks detected.</div>
+            </h1>
+            <div class="ui divider"></div>
+            <p id="loadWarning"><i class="ui loading spinner icon"></i> Loading SMART data...</p>
+                <div id="smart-holder" class="ui unstackable items">
+                  </div>
+            <br>
+            <div class="ui divider"></div>
+        </div>
+        <div class="ui modal">
+          <i class="close icon"></i>
+          <div class="header">
+            SMART Information (<span id="modal_model"></span>)
+          </div>
+          <div class="content">
+            <table class="ui very basic fluid celled table">
+              <thead>
+                <tr><th>ID</th>
+                <th>Name</th>
+                <th>Value</th>
+                <th>Worst</th>
+                <th>Thresh</th>
+                <th>Status</th>
+              </tr></thead>
+              <tbody id="modal_smart">
+                <tr>
+                  <td>
+                    ...
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          <div class="actions">
+            <div class="ui black deny button">
+              Close
             </div>
-    </div>
-
-    <div id="msgbox" class="ts bottom right snackbar">
-        <div class="content">
-            Your request is processing now.
+          </div>
         </div>
-    </div>
-
-    <br><br>
-    <script>
-        ts('.secondary.menu .item').tab();
-        $("#mainmenu").html("");
-        var lastSelectedObject = "";
-        startup();
-
-        function startup() {
-            $.getJSON("../../system/disk/smart/getSMART", function(data) {
+        <script>
+          var smart_template = '<div class="item"><div class="image" style="width: auto !important"><img src="/SystemAO/disk/smart/img/hard-drive.svg" style="height:60px;width:auto"></div><div class="content"><p class="header">{model}</p><button class="ui right floated icon button" id="{id}" onclick="showDetails(this)"><i class="info icon"></i></button><div class="meta"><span>{status}</span></div><div class="description"><p></p></div><div class="extra">{capacity}</div></div></div>';
+          var smartDATA;  
+          $.getJSON("/system/disk/smart/getSMART", function(data) {
+                smartDATA = data;
                 $("#mainmenu").html("");
                 if ($(data).length == 0) {
-                    msg("No harddisk detected.");
-                    MainHTML = "";
-                    MainHTML += "<div class=\"item\">";
-                    MainHTML += "<div class=\"ts comments\">";
-                    MainHTML += "<div class=\"comment\" style=\"cursor:pointer;width:98vw\">";
-                    MainHTML += "<div class=\"avatar\"><i class=\"big caution sign icon\"></i></div>";
-                    MainHTML += "<div class=\"content\">";
-                    MainHTML += "<p class=\"author\">No disk was found on this system</p>";
-                    MainHTML += "<div class=\"text\">Please make sure your disk installed correctly</div>";
-                    MainHTML += "</div>";
-                    MainHTML += "</div>";
-                    MainHTML += "</div>";
-                    MainHTML += "</div>";
-                    $("#mainmenu").append(MainHTML);
+                    $("#smart-holder").append(append("-1","No disk find!","",-1));
+                    $("#healthy").text("No disks detected.");
+                    $("#totaldisk").text("0");
+                }else{
+                  $.each(data.devices, function(index, value) {
+                    $("#smart-holder").append(append(index,value.smart.model_name,value.smart.healthy,value.smart.user_capacity.bytes));
+                  });
+                  $("#healthy").text(data.healthy);
+                  $("#totaldisk").text(data.devices.length);
                 }
-                $.each(data, function(index, value) {
-
-                    if (value["SMART"]["smartctl"]["messages"] !== null) {
-                        if (value["SMART"]["smartctl"]["messages"][0]["severity"] == "error") {
-                            msg(value["SMART"]["smartctl"]["messages"][0]["string"]);
-                            return;
-                        }
-                    }
-
-                    if (value["SMART"]["user_capacity"] !== null) {
-                        var capacity = disksize(value["SMART"]["user_capacity"]["bytes"]);
-                    } else {
-                        var capacity = "Unknown";
-                    }
-                    if (typeof value["SMART"]["model_name"] !== null) {
-                        var model_name = value["SMART"]["model_name"];
-                    } else {
-                        var model_name = "Unknown";
-                    }
-                    //for extended
-                    var location = "This Host";
-                    if (value["SMART"]["temperature"] !== null) {
-                        var temperatureF = Math.round(1.8 * parseInt(value["SMART"]["temperature"]["current"]) + 32);
-                        var temperature = value["SMART"]["temperature"]["current"] + "°C | " + temperatureF + "°F";
-                    } else {
-                        var temperature = "Unknown";
-                    }
-                    if (value["SMART"]["serial_number"] !== null) {
-                        var serial_number = value["SMART"]["serial_number"];
-                    } else {
-                        var serial_number = "Unknown";
-                    }
-                    if (value["SMART"]["firmware_version"] !== null) {
-                        var firmware_version = value["SMART"]["firmware_version"];
-                    } else {
-                        var firmware_version = "Unknown";
-                    }
-                    if (value["SMART"]["ata_smart_attributes"] !== null) {
-                        var smart = "Yes";
-                        var icon = "info";
-                        $.each(value["SMART"]["ata_smart_attributes"]["table"], function(indexf, valuef) {
-                            if (typeof valuef["when_failed"] !== "undefined") {
-                                if (valuef["when_failed"] !== "") { //probabally FAILING_NOW, but not sure.
-                                    icon = "negative";
-                                }
-                            }
-                        });
-                    } else {
-                        var smart = "No";
-                    }
-
-
-
-                    $("#mainmenu").append('<div class="item" ondblclick="showSMART()" onClick="selected(this);" diskid="' + value["Port"] + '" location="' + location + '" temperature="' + temperature + '" serial_number="' + serial_number + '" firmware_version="' + firmware_version + '" smart="' + smart + '"><div class="ts comments"><div class="comment" style="cursor:pointer;"><div class="avatar"><i class="inverted ' + icon + ' circular disk outline icon"></i></div><div class="content"><p class="author">' + value["Port"] + '</p><div class="text">' + model_name + ", " + capacity + '</div></div></div></div></div>');
-
-                });
+                $("#loadWarning").remove();
             });
-        }
-
-        function showSMART() {
-            if ($("div[active='true']").length == 0) {
-                msg("Nothing selected");
-            } else {
-                window.history.pushState("", "", "?disk=" + $("div[active='true']").attr("diskid"));
-                showDialog("table.html?disk=" + $("div[active='true']").attr("diskid"), 300, 300);
-            }
-        }
-
-        function shortTest() {
-            if ($("div[active='true']").length == 0) {
-                msg("Nothing selected");
-            } else {
-                window.history.pushState("", "", "?disk=" + $("div[active='true']").attr("diskid"));
-                showDialog("dotest.html?disk=" + $("div[active='true']").attr("diskid"), 300, 300);
+            
+            function append(id, name, status, capacity){
+              var tmp = smart_template;
+              tmp = tmp.replaceAll("{id}",id);
+              tmp = tmp.replaceAll("{model}",name);
+              tmp = tmp.replaceAll("{status}",status);
+              tmp = tmp.replaceAll("{capacity}",disksize(capacity));
+              return tmp;
             }
-        }
-
-        function selected(object) {
-            if (lastSelectedObject != "") {
-                $(lastSelectedObject).css("border-style", "solid");
-                $(lastSelectedObject).css("border-width", "0px");
-                $(lastSelectedObject).css("border-color", "#ffffff");
-                $(lastSelectedObject).css("background-color", "#ffffff");
-                $(lastSelectedObject).removeAttr("style");
-                $(lastSelectedObject).removeAttr("active");
-                $(lastSelectedObject).children("div[class='ts comments']").children("div[class='comment']").children("div[class='avatar']").children("i[name='arrow']").attr("class", "large chevron down icon")
-            }
-            $(object).css("border-style", "solid");
-            $(object).css("border-width", "1px");
-            $(object).css("border-color", "#5998ff");
-            $(object).css("background-color", "#e2fdff");
-            $(object).attr("active", "true");
-            $(object).attr("active", "true");
-            $(object).children("div[class='ts comments']").children("div[class='comment']").children("div[class='avatar']").children("i[name='arrow']").attr("class", "large chevron up icon")
-            $("#mainmenumsg").appendTo(object);
-            $("#mainmenumsg").show();
-            $("#location").text($(object).attr("location"));
-            $("#temperature").text($(object).attr("temperature"));
-            $("#serial_number").text($(object).attr("serial_number"));
-            $("#firmware_version").text($(object).attr("firmware_version"));
-            $("#smart").text($(object).attr("smart"));
-
-            lastSelectedObject = object;
-
-        }
-
-
 
-
-        function msg(content) {
-            ts('.snackbar').snackbar({
-                content: content,
-                actionEmphasis: 'negative',
-            });
-        }
-
-        function disksize(size) {
+          function disksize(size) {
             if (size >= 1000000000000) {
                 return Math.floor(size / 1000000000000) + " TB";
             } else if (size >= 1000000000) {
@@ -218,29 +95,32 @@
                 return Math.floor(size / 1000000) + " MB";
             } else if (size >= 1024) {
                 return Math.floor(size / 1000) + " KB";
-            } else {
+            } else if (size > 0) {
                 return size + " Bytes";
+            } else if (size == 0) {
+                return "Unknown capacity";
+            } else {
+                return "";
             }
-        }
-
-        function showDialog(href, x, y) {
-            $("#modaldata").html("");
-            if (typeof loadViaSystemSetting !== "undefined") {
-                if (loadViaSystemSetting == true) {
-                    href = "../disk/smart/" + href;
-                }
-            }
-            $("#modaldata").load(href);
-            ts('#modal').modal({
-                approve: '.info',
-                onApprove: function() {
-                    try {
-                        clearInterval(timer);
-                    } catch (err) {}
-                }
-            }).modal("show")
-        }
-    </script>
-</body>
-
+          }
+
+          function showDetails(selector) {
+            $("#modal_smart").html("");
+            var id = $(selector).attr("id");
+            $("#modal_model").text(smartDATA.devices[id].smart.model_name);
+            $.each(smartDATA.devices[id].smart.ata_smart_attributes.table, function(index, value) {
+                    $("#modal_smart").append("<tr>");
+                    $("#modal_smart").append("<td>" + value.id + "</td>");
+                    $("#modal_smart").append("<td>" + value.name + "</td>");
+                    $("#modal_smart").append("<td>" + value.value + "</td>");
+                    $("#modal_smart").append("<td>" + value.worst + "</td>");
+                    $("#modal_smart").append("<td>" + value.thresh + "</td>");
+                    $("#modal_smart").append("<td>" + value.healthy + "</td>");
+                    $("#modal_smart").append("</tr>");
+            });
+            $('.ui.modal').modal('show');
+          }
+        </script>
+   
+    </body>
 </html>

+ 0 - 91
web/SystemAO/disk/smart/table.html

@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<meta name="apple-mobile-web-app-capable" content="yes" />
-<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=0.6, maximum-scale=0.6" />
-<html>
-
-<head>
-    <meta charset="UTF-8">
-    <script type='text/javascript' charset='utf-8'>
-        // Hides mobile browser's address bar when page is done loading.
-        window.addEventListener('load', function(e) {
-            setTimeout(function() {
-                window.scrollTo(0, 1);
-            }, 1);
-        }, false);
-    </script>
-    <title>ArOZ Onlineβ</title>
-    <link rel="stylesheet" href="../../../script/tocas/tocas.css">
-    <script src="../../../script/tocas/tocas.js"></script>
-    <script src="../../../script/jquery.min.js"></script>
-    <!--<script src="../../../script/ao_module.js"></script>-->
-</head>
-
-<body style="background-color: rgba(255, 255, 255,0.9)">
-    <table class="ts celled striped table">
-        <thead>
-            <tr>
-                <thead>
-                    <tr>
-                        <th>#</th>
-                        <th>Name</th>
-                        <th>Value</th>
-                        <th>Worst</th>
-                        <th>Raw Data</th>
-                    </tr>
-                </thead>
-                <tbody id="smartbody">
-                </tbody>
-    </table>
-
-    <script>
-        if (typeof ao_module_getAORootFromScriptPath !== "function") {
-            $.getScript("../../../script/ao_module.js", function() {
-                ao_module_setWindowSize(700, 500);
-            });
-        }
-
-        $.getJSON("../../system/disk/smart/getSMARTTable?disk=" + get("disk"), function(data) {
-            $.each(data, function(index, value) {
-                if (value["id"] !== undefined) {
-                    var id = value["id"];
-                } else {
-                    var id = "Unknown";
-                }
-                if (value["name"] !== undefined) {
-                    var name = value["name"];
-                } else {
-                    var name = "Unknown";
-                }
-                if (value["value"] !== undefined) {
-                    var Svalue = value["value"];
-                } else {
-                    var Svalue = "Unknown";
-                }
-                if (value["worst"] !== undefined) {
-                    var worst = value["worst"];
-                } else {
-                    var worst = "Unknown";
-                }
-                if (typeof value["when_failed"] !== "undefined") {
-                    if (value["when_failed"] !== "") { //probabally FAILING_NOW, but not sure.
-                        var when_failed = "Failed";
-                    } else {
-                        var when_failed = "OK";
-                    }
-                } else {
-                    var when_failed = "Unknown";
-                }
-                $("#smartbody").append('<tr><td>' + id + '</td><td>' + name + '</td><td>' + Svalue + '</td><td>' + worst + '</td><td>' + when_failed + '</td></tr>');
-            });
-        });
-
-        //https://stackoverflow.com/questions/831030/how-to-get-get-request-parameters-in-javascript
-        function get(name) {
-            if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search)) {
-                return decodeURIComponent(name[1]);
-            }
-        }
-    </script>
-</body>
-
-</html>