query status of VILLASnode via VILLASnode API in parallel job #64

This commit is contained in:
Sonja Happ 2021-05-21 13:08:24 +02:00
parent 55fe91c5f4
commit 1b3e4e907c
5 changed files with 164 additions and 0 deletions

View file

@ -77,6 +77,7 @@ func InitConfig() error {
contactMail = flag.String("contact-mail", "svogel2@eonerc.rwth-aachen.de", "EMail of the administrative contact")
testDataPath = flag.String("test-data-path", "", "The path to a test data json file")
groupsPath = flag.String("groups-path", "configuration/groups.yaml", "The path to a YAML file that maps user groups to scenario IDs")
apiUpdateInterval = flag.String("api-update-interval", "10s" /* 10 sec */, "Interval in which API URL is queried for status updates of ICs")
)
flag.Parse()
@ -108,6 +109,7 @@ func InitConfig() error {
"test.datapath": *testDataPath,
"groups.path": *groupsPath,
"config.file": *configFile,
"apiupdateinterval": *apiUpdateInterval,
}
if *dbClear == true {

1
go.mod
View file

@ -8,6 +8,7 @@ require (
github.com/gin-gonic/gin v1.4.0
github.com/go-ini/ini v1.51.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-resty/resty/v2 v2.6.0
github.com/google/uuid v1.1.2
github.com/jinzhu/gorm v1.9.11
github.com/kr/pretty v0.2.1 // indirect

8
go.sum
View file

@ -69,6 +69,8 @@ github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8c
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4=
github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
@ -238,6 +240,8 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
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=
@ -259,6 +263,10 @@ golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/nt
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=

View file

@ -0,0 +1,147 @@
/** infrastructure-component package, API queries.
*
* @author Sonja Happ <sonja.happ@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASweb-backend-go
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
package infrastructure_component
import (
"encoding/json"
"fmt"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
"github.com/go-resty/resty/v2"
"github.com/jinzhu/gorm/dialects/postgres"
"log"
"strconv"
"strings"
"time"
)
func QueryICAPIs(d time.Duration) {
client := resty.New()
//client.SetDebug(true)
go func() {
for _ = range time.Tick(d) {
//log.Println("Querying IC APIs at time:", x)
var err error
db := database.GetDB()
var ics []database.InfrastructureComponent
err = db.Order("ID asc").Find(&ics).Error
if err != nil {
log.Println("Error getting ICs from DB:", err.Error())
continue
}
// iterate over ICs in DB
for _, ic := range ics {
if ic.ManagedExternally {
continue
}
if ic.APIURL == "" || (!strings.HasPrefix(ic.APIURL, "http://") && !strings.HasPrefix(ic.APIURL, "https://")) {
continue
}
if ic.Category == "gateway" && ic.Type == "villas-node" {
log.Println("External API: checking for IC", ic.Name)
statusResponse, err := client.R().SetHeader("Accept", "application/json").Get(ic.APIURL + "/status")
if err != nil {
log.Println("Error querying status of", ic.Name, err)
continue
}
var status map[string]interface{}
err = json.Unmarshal(statusResponse.Body(), &status)
if err != nil {
log.Println("Error unmarshalling status of", ic.Name, err)
continue
}
parts := strings.Split(ic.WebsocketURL, "/")
if len(parts) > 0 && parts[len(parts)-1] != "" {
configResponse, _ := client.R().SetHeader("Accept", "application/json").Get(ic.APIURL + "/node/" + parts[len(parts)-1])
statsResponse, _ := client.R().SetHeader("Accept", "application/json").Get(ic.APIURL + "/node/" + parts[len(parts)-1] + "/stats")
var config map[string]interface{}
err = json.Unmarshal(configResponse.Body(), &config)
if err == nil {
status["config"] = config
}
var stats map[string]interface{}
err = json.Unmarshal(statsResponse.Body(), &stats)
if err == nil {
status["statistics"] = stats
}
}
var updatedIC UpdateICRequest
statusRaw, _ := json.Marshal(status)
updatedIC.InfrastructureComponent.StatusUpdateRaw = postgres.Jsonb{RawMessage: statusRaw}
updatedIC.InfrastructureComponent.State = fmt.Sprintf("%v", status["state"])
updatedIC.InfrastructureComponent.UUID = fmt.Sprintf("%v", status["uuid"])
timeNow, myerr := strconv.ParseFloat(fmt.Sprintf("%v", status["time_now"]), 64)
if myerr != nil {
log.Println("Error parsing time_now to float", myerr.Error())
continue
}
timeStarted, myerr := strconv.ParseFloat(fmt.Sprintf("%v", status["time_started"]), 64)
if myerr != nil {
log.Println("Error parsing time_started to float", myerr.Error())
continue
}
uptime := timeNow - timeStarted
updatedIC.InfrastructureComponent.Uptime = uptime
// validate the update
err = updatedIC.validate()
if err != nil {
log.Println("Error validating updated IC", ic.Name, ic.UUID, err.Error())
continue
}
// create the update and update IC in DB
var x InfrastructureComponent
err = x.byID(ic.ID)
if err != nil {
log.Println("Error getting IC by ID", ic.Name, err)
continue
}
u := updatedIC.updatedIC(x)
err = x.update(u)
if err != nil {
log.Println("Error updating IC", ic.Name, ic.UUID, err.Error())
continue
}
} else if ic.Category == "manager" && ic.Type == "villas-relay" {
} else if ic.Category == "gateway" && ic.Type == "villas-relay" {
}
}
}
}()
}

View file

@ -24,6 +24,7 @@ package main
import (
"fmt"
"log"
"time"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration"
"git.rwth-aachen.de/acs/public/villas/web-backend-go/database"
@ -140,6 +141,11 @@ func main() {
log.Fatal(err)
}
// Update via external APIs of ICs (if not managed via AMQP)
intervalStr, _ := configuration.GlobalConfig.String("apiupdateinterval")
interval, _ := time.ParseDuration(intervalStr)
infrastructure_component.QueryICAPIs(interval)
log.Println("Running...")
// Server at port 4000 to match frontend's redirect path
r.Run(":" + port)