2021-02-13 16:06:13 +01:00
package tasks
2021-02-13 15:51:14 +01:00
import (
"database/sql"
2021-02-14 01:04:50 +01:00
"encoding/json"
2021-02-13 21:49:09 +01:00
"fmt"
2021-02-14 03:50:21 +01:00
"log"
2021-02-13 21:49:09 +01:00
"strconv"
2021-02-13 15:51:14 +01:00
2021-03-04 13:43:49 +01:00
"github.com/edgebox-iot/edgeboxctl/internal/diagnostics"
"github.com/edgebox-iot/edgeboxctl/internal/edgeapps"
"github.com/edgebox-iot/edgeboxctl/internal/utils"
2021-02-13 16:06:13 +01:00
_ "github.com/go-sql-driver/mysql" // Mysql Driver
2021-05-02 10:52:32 +02:00
_ "github.com/mattn/go-sqlite3" // SQlite Driver
2021-02-13 15:51:14 +01:00
)
2021-02-13 17:04:57 +01:00
// Task : Struct for Task type
type Task struct {
ID int ` json:"id" `
Task string ` json:"task" `
Args string ` json:"args" `
Status string ` json:"status" `
Result sql . NullString ` json:"result" ` // Database fields that can be null must use the sql.NullString type
Created string ` json:"created" `
Updated string ` json:"updated" `
}
2021-02-14 05:22:08 +01:00
type taskSetupTunnelArgs struct {
2021-02-14 01:04:50 +01:00
BootnodeAddress string ` json:"bootnode_address" `
BootnodeToken string ` json:"bootnode_token" `
AssignedAddress string ` json:"assigned_address" `
2021-02-14 02:28:13 +01:00
NodeName string ` json:"node_name" `
2021-02-14 01:04:50 +01:00
}
2021-02-18 23:59:14 +01:00
type taskStartEdgeAppArgs struct {
ID string ` json:"id" `
}
2021-03-04 16:06:54 +01:00
type taskInstallEdgeAppArgs struct {
ID string ` json:"id" `
}
type taskRemoveEdgeAppArgs struct {
ID string ` json:"id" `
}
2021-02-18 23:59:14 +01:00
type taskStopEdgeAppArgs struct {
ID string ` json:"id" `
}
2021-02-20 15:26:23 +01:00
type taskEnableOnlineArgs struct {
ID string ` json:"id" `
InternetURL string ` json:"internet_url" `
}
type taskDisableOnlineArgs struct {
ID string ` json:"id" `
}
2021-02-13 17:04:57 +01:00
// GetNextTask : Performs a MySQL query over the device's Edgebox API
func GetNextTask ( ) Task {
2021-02-13 15:51:14 +01:00
// Will try to connect to API database, which should be running locally under WS.
2021-05-02 10:52:32 +02:00
db , err := sql . Open ( "sqlite3" , utils . GetSQLiteDbConnectionDetails ( ) )
2021-02-13 15:51:14 +01:00
// if there is an error opening the connection, handle it
if err != nil {
panic ( err . Error ( ) )
}
2021-05-02 10:52:32 +02:00
results , err := db . Query ( "SELECT * FROM task WHERE status = 0 ORDER BY created ASC LIMIT 1;" )
2021-02-13 15:51:14 +01:00
// if there is an error inserting, handle it
if err != nil {
panic ( err . Error ( ) )
}
2021-02-13 17:04:57 +01:00
var task Task
for results . Next ( ) {
// for each row, scan the result into our task composite object
err = results . Scan ( & task . ID , & task . Task , & task . Args , & task . Status , & task . Result , & task . Created , & task . Updated )
if err != nil {
panic ( err . Error ( ) ) // proper error handling instead of panic in your app
}
}
2021-05-08 22:42:07 +02:00
results . Close ( )
db . Close ( )
2021-02-13 17:04:57 +01:00
return task
}
2021-02-13 21:49:09 +01:00
// ExecuteTask : Performs execution of the given task, updating the task status as it goes, and publishing the task result
func ExecuteTask ( task Task ) Task {
2021-02-13 17:04:57 +01:00
2021-05-02 10:52:32 +02:00
db , err := sql . Open ( "sqlite3" , utils . GetSQLiteDbConnectionDetails ( ) )
2021-02-13 17:04:57 +01:00
2021-02-13 21:49:09 +01:00
if err != nil {
panic ( err . Error ( ) )
}
2021-02-13 17:04:57 +01:00
2021-05-08 22:42:07 +02:00
statement , err := db . Prepare ( "UPDATE task SET status = ?, updated = ? WHERE ID = ?" ) // Prepare SQL Statement
if err != nil {
log . Fatal ( err . Error ( ) )
}
2021-02-13 21:49:09 +01:00
2021-05-08 22:42:07 +02:00
_ , err = statement . Exec ( 1 , "datetime('now')" , strconv . Itoa ( task . ID ) ) // Execute SQL Statement
2021-02-13 21:49:09 +01:00
if err != nil {
2021-05-08 22:42:07 +02:00
log . Fatal ( err . Error ( ) )
2021-02-13 21:49:09 +01:00
}
2021-02-15 20:37:16 +01:00
if diagnostics . Version == "dev" {
2021-02-14 03:50:21 +01:00
log . Printf ( "Dev environemnt. Not executing tasks." )
2021-02-14 01:04:50 +01:00
} else {
2021-02-14 05:22:08 +01:00
log . Println ( "Task: " + task . Task )
2021-02-14 01:04:50 +01:00
switch task . Task {
2021-02-14 05:22:08 +01:00
case "setup_tunnel" :
2021-02-14 01:04:50 +01:00
2021-02-14 03:50:21 +01:00
log . Println ( "Setting up bootnode connection..." )
2021-02-14 05:22:08 +01:00
var args taskSetupTunnelArgs
2021-02-14 01:04:50 +01:00
err := json . Unmarshal ( [ ] byte ( task . Args ) , & args )
if err != nil {
2021-02-14 03:50:21 +01:00
log . Printf ( "Error reading arguments of setup_bootnode task: %s" , err )
2021-02-14 01:04:50 +01:00
} else {
2021-02-14 05:22:08 +01:00
taskResult := taskSetupTunnel ( args )
2021-02-14 03:50:21 +01:00
task . Result = sql . NullString { String : taskResult , Valid : true }
2021-02-14 01:04:50 +01:00
}
2021-03-04 16:06:54 +01:00
case "install_edgeapp" :
log . Println ( "Installing EdgeApp..." )
var args taskInstallEdgeAppArgs
err := json . Unmarshal ( [ ] byte ( task . Args ) , & args )
if err != nil {
log . Printf ( "Error reading arguments of install_edgeapp task: %s" , err )
} else {
taskResult := taskInstallEdgeApp ( args )
task . Result = sql . NullString { String : taskResult , Valid : true }
}
case "remove_edgeapp" :
log . Println ( "Removing EdgeApp..." )
var args taskRemoveEdgeAppArgs
err := json . Unmarshal ( [ ] byte ( task . Args ) , & args )
if err != nil {
log . Printf ( "Error reading arguments of remove_edgeapp task: %s" , err )
} else {
taskResult := taskRemoveEdgeApp ( args )
task . Result = sql . NullString { String : taskResult , Valid : true }
}
2021-02-14 01:04:50 +01:00
case "start_edgeapp" :
2021-02-18 23:59:14 +01:00
log . Println ( "Starting EdgeApp..." )
var args taskStartEdgeAppArgs
err := json . Unmarshal ( [ ] byte ( task . Args ) , & args )
if err != nil {
log . Printf ( "Error reading arguments of start_edgeapp task: %s" , err )
} else {
taskResult := taskStartEdgeApp ( args )
task . Result = sql . NullString { String : taskResult , Valid : true }
}
2021-02-14 01:04:50 +01:00
case "stop_edgeapp" :
2021-02-18 23:59:14 +01:00
log . Println ( "Stopping EdgeApp..." )
var args taskStopEdgeAppArgs
err := json . Unmarshal ( [ ] byte ( task . Args ) , & args )
if err != nil {
log . Printf ( "Error reading arguments of stop_edgeapp task: %s" , err )
} else {
taskResult := taskStopEdgeApp ( args )
task . Result = sql . NullString { String : taskResult , Valid : true }
}
2021-02-20 15:26:23 +01:00
case "enable_online" :
log . Println ( "Enabling online access to EdgeApp..." )
var args taskEnableOnlineArgs
err := json . Unmarshal ( [ ] byte ( task . Args ) , & args )
if err != nil {
log . Printf ( "Error reading arguments of enable_online task: %s" , err )
} else {
taskResult := taskEnableOnline ( args )
task . Result = sql . NullString { String : taskResult , Valid : true }
}
case "disable_online" :
log . Println ( "Disabling online access to EdgeApp..." )
var args taskDisableOnlineArgs
err := json . Unmarshal ( [ ] byte ( task . Args ) , & args )
if err != nil {
log . Printf ( "Error reading arguments of enable_online task: %s" , err )
} else {
taskResult := taskDisableOnline ( args )
task . Result = sql . NullString { String : taskResult , Valid : true }
}
2021-02-14 01:04:50 +01:00
}
2021-02-20 15:26:23 +01:00
2021-02-13 21:49:09 +01:00
}
2021-05-08 22:42:07 +02:00
statement , err = db . Prepare ( "Update task SET status = 2, result = '" + task . Result . String + "', updated = datetime('now') WHERE ID = " + strconv . Itoa ( task . ID ) + ";" ) // Prepare SQL Statement
if err != nil {
log . Fatal ( err . Error ( ) )
}
if err != nil {
log . Fatal ( err . Error ( ) )
}
2021-02-13 21:49:09 +01:00
if task . Result . Valid {
2021-05-08 22:42:07 +02:00
_ , err = statement . Exec ( 2 , task . Result . String , "datetime('now')" , strconv . Itoa ( task . ID ) ) // Execute SQL Statement with result info
if err != nil {
log . Fatal ( err . Error ( ) )
}
2021-02-13 21:49:09 +01:00
} else {
2021-05-08 22:42:07 +02:00
_ , err = statement . Exec ( 3 , "Error" , "datetime('now')" , strconv . Itoa ( task . ID ) ) // Execute SQL Statement with Error info
if err != nil {
log . Fatal ( err . Error ( ) )
}
2021-02-13 21:49:09 +01:00
}
if err != nil {
panic ( err . Error ( ) )
}
2021-05-08 22:42:07 +02:00
db . Close ( )
2021-02-13 21:49:09 +01:00
returnTask := task
2021-02-13 15:51:14 +01:00
2021-02-13 21:49:09 +01:00
return returnTask
2021-02-13 15:51:14 +01:00
}
2021-02-14 01:04:50 +01:00
2021-02-15 19:14:46 +01:00
// ExecuteSchedules - Run Specific tasks without input each multiple x of ticks.
func ExecuteSchedules ( tick int ) {
2021-02-15 20:37:16 +01:00
if tick == 1 {
// Executing on startup (first tick). Schedules run before tasks in the SystemIterator
2021-02-17 13:34:53 +01:00
log . Println ( taskGetEdgeApps ( ) )
2021-02-15 20:37:16 +01:00
}
2021-02-15 19:14:46 +01:00
if tick % 30 == 0 {
// Executing every 30 ticks
2021-02-17 13:34:53 +01:00
log . Println ( taskGetEdgeApps ( ) )
2021-02-15 19:14:46 +01:00
}
if tick % 60 == 0 {
// Every 60 ticks...
}
// Just add a schedule here if you need a custom one (every "tick hour", every "tick day", etc...)
}
2021-02-14 05:22:08 +01:00
func taskSetupTunnel ( args taskSetupTunnelArgs ) string {
2021-02-14 01:04:50 +01:00
2021-02-14 05:22:08 +01:00
fmt . Println ( "Executing taskSetupTunnel" )
2021-02-14 03:50:21 +01:00
2021-02-15 09:55:09 +01:00
cmdargs := [ ] string { "gen" , "--name" , args . NodeName , "--token" , args . BootnodeToken , args . BootnodeAddress + ":8655" , "--prefix" , args . AssignedAddress }
2021-02-15 20:37:16 +01:00
utils . Exec ( "tinc-boot" , cmdargs )
2021-02-14 01:04:50 +01:00
2021-02-14 05:22:08 +01:00
cmdargs = [ ] string { "start" , "tinc@dnet" }
2021-02-15 20:37:16 +01:00
utils . Exec ( "systemctl" , cmdargs )
2021-02-14 01:04:50 +01:00
2021-02-14 05:22:08 +01:00
cmdargs = [ ] string { "enable" , "tinc@dnet" }
2021-02-15 20:37:16 +01:00
utils . Exec ( "systemctl" , cmdargs )
2021-02-14 01:04:50 +01:00
2021-02-14 05:22:08 +01:00
output := "OK" // Better check / logging of command execution result.
2021-02-14 01:04:50 +01:00
return output
}
2021-03-04 16:06:54 +01:00
func taskInstallEdgeApp ( args taskInstallEdgeAppArgs ) string {
fmt . Println ( "Executing taskInstallEdgeApp for " + args . ID )
result := edgeapps . SetEdgeAppInstalled ( args . ID )
resultJSON , _ := json . Marshal ( result )
taskGetEdgeApps ( )
return string ( resultJSON )
}
func taskRemoveEdgeApp ( args taskRemoveEdgeAppArgs ) string {
fmt . Println ( "Executing taskRemoveEdgeApp for " + args . ID )
2021-03-04 16:53:49 +01:00
// Making sure the application is stopped before setting it as removed.
edgeapps . StopEdgeApp ( args . ID )
2021-03-04 16:06:54 +01:00
result := edgeapps . SetEdgeAppNotInstalled ( args . ID )
resultJSON , _ := json . Marshal ( result )
taskGetEdgeApps ( )
return string ( resultJSON )
}
2021-02-18 23:59:14 +01:00
func taskStartEdgeApp ( args taskStartEdgeAppArgs ) string {
fmt . Println ( "Executing taskStartEdgeApp for " + args . ID )
result := edgeapps . RunEdgeApp ( args . ID )
2021-02-19 01:32:37 +01:00
2021-02-18 23:59:14 +01:00
resultJSON , _ := json . Marshal ( result )
taskGetEdgeApps ( ) // This task will imediatelly update the entry in the api database.
return string ( resultJSON )
}
func taskStopEdgeApp ( args taskStopEdgeAppArgs ) string {
fmt . Println ( "Executing taskStopEdgeApp for " + args . ID )
result := edgeapps . StopEdgeApp ( args . ID )
2021-02-19 01:32:37 +01:00
2021-02-18 23:59:14 +01:00
resultJSON , _ := json . Marshal ( result )
taskGetEdgeApps ( ) // This task will imediatelly update the entry in the api database.
return string ( resultJSON )
}
2021-02-20 15:26:23 +01:00
func taskEnableOnline ( args taskEnableOnlineArgs ) string {
fmt . Println ( "Executing taskEnableOnline for " + args . ID )
result := edgeapps . EnableOnline ( args . ID , args . InternetURL )
resultJSON , _ := json . Marshal ( result )
taskGetEdgeApps ( )
return string ( resultJSON )
}
func taskDisableOnline ( args taskDisableOnlineArgs ) string {
2021-02-20 19:09:41 +01:00
fmt . Println ( "Executing taskDisableOnline for " + args . ID )
2021-02-20 15:26:23 +01:00
result := edgeapps . DisableOnline ( args . ID )
resultJSON , _ := json . Marshal ( result )
taskGetEdgeApps ( )
return string ( resultJSON )
}
2021-02-15 19:14:46 +01:00
func taskGetEdgeApps ( ) string {
fmt . Println ( "Executing taskGetEdgeApps" )
2021-02-17 01:08:10 +01:00
2021-02-17 12:10:15 +01:00
edgeApps := edgeapps . GetEdgeApps ( )
edgeAppsJSON , _ := json . Marshal ( edgeApps )
2021-05-02 10:52:32 +02:00
db , err := sql . Open ( "sqlite3" , utils . GetSQLiteDbConnectionDetails ( ) )
2021-02-17 13:34:53 +01:00
if err != nil {
2021-05-08 22:42:07 +02:00
log . Fatal ( err . Error ( ) )
2021-02-17 13:34:53 +01:00
}
2021-02-17 12:10:15 +01:00
2021-05-08 22:42:07 +02:00
statement , err := db . Prepare ( "REPLACE into option (name, value, created, updated) VALUES (?, ?, ?, ?);" ) // Prepare SQL Statement
if err != nil {
log . Fatal ( err . Error ( ) )
}
2021-02-17 12:10:15 +01:00
2021-05-08 22:42:07 +02:00
_ , err = statement . Exec ( "EDGEAPPS_LIST" , string ( edgeAppsJSON ) , "datetime('now')" , "datetime('now')" ) // Execute SQL Statement
2021-02-17 13:34:53 +01:00
if err != nil {
2021-05-08 22:42:07 +02:00
log . Fatal ( err . Error ( ) )
2021-02-17 13:34:53 +01:00
}
2021-02-17 12:10:15 +01:00
2021-05-08 22:42:07 +02:00
db . Close ( )
2021-02-17 13:34:53 +01:00
return string ( edgeAppsJSON )
2021-02-15 19:14:46 +01:00
}