package web import ( "fmt" "github.com/analogj/scrutiny/webapp/backend/pkg/config" "github.com/analogj/scrutiny/webapp/backend/pkg/database" "github.com/analogj/scrutiny/webapp/backend/pkg/metadata" "github.com/analogj/scrutiny/webapp/backend/pkg/models/collector" dbModels "github.com/analogj/scrutiny/webapp/backend/pkg/models/db" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" log "github.com/sirupsen/logrus" "net/http" ) type AppEngine struct { Config config.Interface } func (ae *AppEngine) Start() error { r := gin.Default() r.Use(database.DatabaseHandler(ae.Config.GetString("web.database.location"))) api := r.Group("/api") { api.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "success": true, }) }) //TODO: notifications api.POST("/devices/register", RegisterDevices) api.GET("/summary", GetDevicesSummary) api.POST("/device/:wwn/smart", UploadDeviceSmartData) api.POST("/device/:wwn/selftest", UploadDeviceSelfTestData) api.GET("/device/:wwn/details", GetDeviceDetails) } //Static request routing r.StaticFS("/web", http.Dir(ae.Config.GetString("web.src.frontend.path"))) //redirect base url to /web r.GET("/", func(c *gin.Context) { c.Redirect(http.StatusFound, "/web") }) //catch-all, serve index page. r.NoRoute(func(c *gin.Context) { c.File(fmt.Sprintf("%s/index.html", ae.Config.GetString("web.src.frontend.path"))) }) return r.Run(fmt.Sprintf("%s:%s", ae.Config.GetString("web.listen.host"), ae.Config.GetString("web.listen.port"))) // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080") } // filter devices that are detected by various collectors. func RegisterDevices(c *gin.Context) { db := c.MustGet("DB").(*gorm.DB) var collectorDeviceWrapper dbModels.DeviceWrapper err := c.BindJSON(&collectorDeviceWrapper) if err != nil { log.Error("Cannot parse detected devices") c.JSON(http.StatusOK, gin.H{"success": false}) } //TODO: filter devices here (remove excludes, force includes) for _, dev := range collectorDeviceWrapper.Data { //insert devices into DB if not already there. db.Where(dbModels.Device{WWN: dev.WWN}).FirstOrCreate(&dev) } if err != nil { c.JSON(http.StatusOK, gin.H{ "success": false, }) } else { c.JSON(http.StatusOK, dbModels.DeviceWrapper{ Success: true, Data: collectorDeviceWrapper.Data, }) } } func UploadDeviceSmartData(c *gin.Context) { db := c.MustGet("DB").(*gorm.DB) var collectorSmartData collector.SmartInfo err := c.BindJSON(&collectorSmartData) if err != nil { //TODO: cannot parse smart data log.Error("Cannot parse SMART data") c.JSON(http.StatusOK, gin.H{"success": false}) } //update the device information if necessary var device dbModels.Device db.Where("wwn = ?", c.Param("wwn")).First(&device) device.UpdateFromCollectorSmartInfo(collectorSmartData) db.Model(&device).Updates(device) // insert smart info deviceSmartData := dbModels.Smart{} err = deviceSmartData.FromCollectorSmartInfo(c.Param("wwn"), collectorSmartData) if err != nil { c.JSON(http.StatusOK, gin.H{"success": false}) return } db.Create(&deviceSmartData) c.JSON(http.StatusOK, gin.H{"success": true}) } func UploadDeviceSelfTestData(c *gin.Context) { } func GetDeviceDetails(c *gin.Context) { db := c.MustGet("DB").(*gorm.DB) device := dbModels.Device{} db.Debug(). Preload("SmartResults", func(db *gorm.DB) *gorm.DB { return db.Order("smarts.created_at DESC").Limit(40) }). Preload("SmartResults.SmartAttributes"). Where("wwn = ?", c.Param("wwn")). First(&device) device.SquashHistory() device.ApplyMetadataRules() c.JSON(http.StatusOK, gin.H{"success": true, "data": device, "lookup": metadata.AtaSmartAttributes}) } func GetDevicesSummary(c *gin.Context) { db := c.MustGet("DB").(*gorm.DB) devices := []dbModels.Device{} //OLD: cant seem to figure out how to get the latest SmartResults for each Device, so instead // we're going to assume that results were retrieved at the same time, so we'll just get the last x number of results //var devicesCount int //db.Table("devices").Count(&devicesCount) //We need the last x (for now all) Smart objects for each Device, so that we can graph Temperature //We also need the last db.Debug(). Preload("SmartResults", func(db *gorm.DB) *gorm.DB { return db.Order("smarts.created_at DESC") //OLD: .Limit(devicesCount) }). //Preload("SmartResults"). // Preload("SmartResults.SmartAttributes"). Find(&devices) //for _, dev := range devices { // log.Printf("===== device: %s\n", dev.WWN) // log.Print(len(dev.SmartResults)) //} //a, _ := json.Marshal(devices) //get json byte array //n := len(a) //Find the length of the byte array //s := string(a[:n]) //convert to string //log.Print(s) //write to response c.JSON(http.StatusOK, gin.H{ "success": true, "data": devices, }) //c.Data(http.StatusOK, "application/json", a) }