edgeboxctl/internal/tasks/tasks.go

197 lines
4.7 KiB
Go

package tasks
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"os/exec"
"strconv"
_ "github.com/go-sql-driver/mysql" // Mysql Driver
)
// Version : The release version
var Version string
// Commit : The commit of this release
var Commit string
// BuildDate : The release build date
var BuildDate string
// Dbhost : Database host (can be tweaked in makefile)
var Dbhost string
// Dbname : Database name (can be tweaked in makefile)
var Dbname string
// Dbuser : Database user (can be tweaked in makefile)
var Dbuser string
// Dbpass : Database password (can be tweaked in)
var Dbpass string
// 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"`
}
type taskSetupBootnodeArgs struct {
BootnodeAddress string `json:"bootnode_address"`
BootnodeToken string `json:"bootnode_token"`
AssignedAddress string `json:"assigned_address"`
NodeName string `json:"node_name"`
}
// GetNextTask : Performs a MySQL query over the device's Edgebox API
func GetNextTask() Task {
// Will try to connect to API database, which should be running locally under WS.
db, err := sql.Open("mysql", Dbuser+":"+Dbpass+"@tcp("+Dbhost+")/"+Dbname)
// if there is an error opening the connection, handle it
if err != nil {
panic(err.Error())
}
// defer the close till after the main function has finished executing
defer db.Close()
// perform a db.Query insert
results, err := db.Query("SELECT * FROM tasks WHERE status = 0 ORDER BY created ASC LIMIT 1;")
// if there is an error inserting, handle it
if err != nil {
panic(err.Error())
}
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
}
}
// be careful deferring Queries if you are using transactions
defer results.Close()
return task
}
// ExecuteTask : Performs execution of the given task, updating the task status as it goes, and publishing the task result
func ExecuteTask(task Task) Task {
db, err := sql.Open("mysql", Dbuser+":"+Dbpass+"@tcp("+Dbhost+")/"+Dbname)
if err != nil {
panic(err.Error())
}
defer db.Close()
statusUpdate, err := db.Query("UPDATE tasks SET status = 1 WHERE ID = " + strconv.Itoa(task.ID))
if err != nil {
panic(err.Error())
}
for statusUpdate.Next() {
}
if Version == "dev" {
log.Printf("Dev environemnt. Not executing tasks.")
} else {
switch task.Task {
case "setup_bootnode":
log.Println("Setting up bootnode connection...")
var args taskSetupBootnodeArgs
err := json.Unmarshal([]byte(task.Args), &args)
if err != nil {
log.Printf("Error reading arguments of setup_bootnode task: %s", err)
} else {
taskResult = taskSetupBootnode(args)
task.Result = sql.NullString{String: taskResult, Valid: true}
}
case "start_edgeapp":
log.Printf("Starting EdgeApp...")
task.Result = sql.NullString{String: taskStartEdgeApp(), Valid: true}
// ...
case "stop_edgeapp":
log.Printf("Stopping EdgeApp...")
task.Result = sql.NullString{String: taskStopEdgeApp(), Valid: true}
// ...
}
}
if task.Result.Valid {
db.Query("Update tasks SET status = 2, result = '" + task.Result.String + "' WHERE ID = " + strconv.Itoa(task.ID) + ";")
} else {
db.Query("Update tasks SET status = 2, result = 'Invalid Task' WHERE ID = " + strconv.Itoa(task.ID) + ";")
}
if err != nil {
panic(err.Error())
}
returnTask := task
return returnTask
}
// Internal functions, for each task
func taskSetupBootnode(args taskSetupBootnodeArgs) string {
fmt.Println("Executing taskSetupBootnode")
out, err := exec.Command("tinc-boot", "gen", "--name "+args.NodeName, "--token "+args.BootnodeToken, args.BootnodeAddress+":8655", "--prefix "+args.AssignedAddress).Output()
if err != nil {
log.Printf("Error: %s", err)
}
output := string(out[:])
fmt.Println(output)
out, err = exec.Command("systemctl", "start", "tinc@dnet").Output()
if err != nil {
log.Printf("Error: %s", err)
}
output = string(out[:])
log.Printf(output)
out, err = exec.Command("systemctl", "enable", "tinc@dnet").Output()
if err != nil {
log.Printf("Error: %s", err)
}
output = string(out[:])
log.Printf(output)
return output
}
func taskStartEdgeApp() string {
return "OK"
}
func taskStopEdgeApp() string {
return "OK"
}