[TASK] add console to backend

This commit is contained in:
Martin Geno 2017-05-30 16:39:14 +02:00
parent 2e5873a541
commit 7aa5896c4f
No known key found for this signature in database
GPG Key ID: F0D39A37E925E941
10 changed files with 89 additions and 18 deletions

View File

@ -25,6 +25,7 @@ var (
configFile string configFile string
config *configPackage.Config config *configPackage.Config
nodes *runtime.Nodes nodes *runtime.Nodes
commands *runtime.Commands
yanicDialer *yanic.Dialer yanicDialer *yanic.Dialer
stats *runtimeYanic.GlobalStats stats *runtimeYanic.GlobalStats
) )
@ -38,14 +39,15 @@ func main() {
log.Log.Info("starting...") log.Log.Info("starting...")
sshmanager := ssh.NewManager(config.SSHPrivateKey) sshmanager := ssh.NewManager(config.SSHPrivateKey)
nodes := runtime.NewNodes(config.StatePath, config.SSHInterface, sshmanager) nodes = runtime.NewNodes(config.StatePath, config.SSHInterface, sshmanager)
commands = runtime.NewCommands(sshmanager)
nodesUpdateWorker := worker.NewWorker(time.Duration(3)*time.Minute, nodes.Updater) nodesUpdateWorker := worker.NewWorker(time.Duration(3)*time.Minute, nodes.Updater)
nodesSaveWorker := worker.NewWorker(time.Duration(3)*time.Second, nodes.Saver) nodesSaveWorker := worker.NewWorker(time.Duration(3)*time.Second, nodes.Saver)
go nodesUpdateWorker.Start() go nodesUpdateWorker.Start()
go nodesSaveWorker.Start() go nodesSaveWorker.Start()
websocket.Start(nodes) websocket.Start(nodes, commands)
if config.Yanic.Enable { if config.Yanic.Enable {
yanicDialer := yanic.Dial(config.Yanic.Type, config.Yanic.Address) yanicDialer := yanic.Dial(config.Yanic.Type, config.Yanic.Address)

44
runtime/cmd.go Normal file
View File

@ -0,0 +1,44 @@
package runtime
import (
"time"
"github.com/FreifunkBremen/freifunkmanager/ssh"
)
type Commands struct {
List map[string]*Command
mgmt *ssh.Manager
}
type Command struct {
ssh.List
Timestemp time.Time `json:"timestemp"`
ID string `json:"id"`
}
func NewCommands(mgmt *ssh.Manager) *Commands {
return &Commands{
mgmt: mgmt,
List: make(map[string]*Command),
}
}
func (cmds *Commands) AddCommand(c *Command) *Command {
cmd := mapCommand(cmds.mgmt, c)
cmds.List[cmd.ID] = cmd
return cmd
}
func mapCommand(mgmt *ssh.Manager, c *Command) *Command {
list := mgmt.CreateList(c.Command)
command := &Command{List: *list}
command.ID = c.ID
command.Timestemp = c.Timestemp
return command
}
func (cmd *Command) Run(f func()) {
cmd.List.Run()
f()
}

View File

@ -7,7 +7,7 @@ import (
) )
type List struct { type List struct {
cmd string `json:"cmd"` Command string `json:"cmd"`
Clients map[string]*ListResult `json:"clients"` Clients map[string]*ListResult `json:"clients"`
sshManager *Manager sshManager *Manager
} }
@ -20,7 +20,7 @@ type ListResult struct {
func (m *Manager) CreateList(cmd string) *List { func (m *Manager) CreateList(cmd string) *List {
list := &List{ list := &List{
cmd: cmd, Command: cmd,
sshManager: m, sshManager: m,
Clients: make(map[string]*ListResult), Clients: make(map[string]*ListResult),
} }
@ -42,7 +42,7 @@ func (l List) Run() {
func (l List) runlistelement(host string, client *ListResult, wg *sync.WaitGroup) { func (l List) runlistelement(host string, client *ListResult, wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
result, err := l.sshManager.run(host, client.ssh, l.cmd) result, err := l.sshManager.run(host, client.ssh, l.Command)
client.Running = false client.Running = false
if err != nil { if err != nil {
client.WithError = true client.WithError = true

View File

@ -26,7 +26,6 @@
width: 15%; width: 15%;
} }
.console .cmd > div { .console .cmd > div {
clear: both;
background-color: #ccc; background-color: #ccc;
margin-bottom: 3px; margin-bottom: 3px;
} }
@ -34,3 +33,9 @@
width: 15%; width: 15%;
height: 20px; height: 20px;
} }
.console .cmd > div > div {
clear: both;
}
.console .cmd div .status {
width: 20px;
}

View File

@ -120,6 +120,7 @@ const guiConsole = {};
if (cmd.clients) { if (cmd.clients) {
Object.keys(cmd.clients).forEach((addr) => { Object.keys(cmd.clients).forEach((addr) => {
console.log(cmd, row, addr);
const clientEl = domlib.newAt(row.clientsContainer, 'div'), const clientEl = domlib.newAt(row.clientsContainer, 'div'),
clients = { clients = {
'host': domlib.newAt(clientEl, 'span'), 'host': domlib.newAt(clientEl, 'span'),

View File

@ -36,9 +36,7 @@ let socket = {'readyState': 0};
} }
break; break;
case 'cmd': case 'cmd':
if (msg.body) { store.updateCMD(msg.cmd);
store.updateCMD(msg.body);
}
break; break;
default: default:
notify.send('warn', `unable to identify message: ${raw}`); notify.send('warn', `unable to identify message: ${raw}`);
@ -69,7 +67,7 @@ let socket = {'readyState': 0};
function sendcmd (cmd) { function sendcmd (cmd) {
const notifyMsg = `Befehl '${cmd.cmd}' wird überall ausgeführt.`, const notifyMsg = `Befehl '${cmd.cmd}' wird überall ausgeführt.`,
socketMsg = JSON.stringify({ socketMsg = JSON.stringify({
'body': cmd, 'cmd': cmd,
'type': 'cmd' 'type': 'cmd'
}); });

View File

@ -2,8 +2,10 @@ package websocket
import ( import (
"io" "io"
"time"
"github.com/genofire/golang-lib/log" "github.com/genofire/golang-lib/log"
"github.com/genofire/golang-lib/worker"
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
) )
@ -53,23 +55,38 @@ func (c *Client) Close() {
func (c *Client) Listen() { func (c *Client) Listen() {
go c.listenWrite() go c.listenWrite()
c.Write(&Message{Type: MessageTypeStats, Body: stats}) c.Write(&Message{Type: MessageTypeStats, Body: stats})
c.allNodes() c.publishAllData()
c.listenRead() c.listenRead()
} }
func (c *Client) allNodes() { func (c *Client) publishAllData() {
for _, node := range nodes.List { for _, node := range nodes.List {
c.Write(&Message{Type: MessageTypeSystemNode, Node: node}) c.Write(&Message{Type: MessageTypeSystemNode, Node: node})
} }
for _, node := range nodes.Current { for _, node := range nodes.Current {
c.Write(&Message{Type: MessageTypeCurrentNode, Node: node}) c.Write(&Message{Type: MessageTypeCurrentNode, Node: node})
} }
for _, cmd := range commands.List {
c.Write(&Message{Type: MessageTypeCommand, Command: cmd})
}
} }
func (c *Client) handleMessage(msg *Message) { func (c *Client) handleMessage(msg *Message) {
switch msg.Type { switch msg.Type {
case MessageTypeSystemNode: case MessageTypeSystemNode:
nodes.UpdateNode(msg.Node) nodes.UpdateNode(msg.Node)
break
case MessageTypeCommand:
cmd := commands.AddCommand(msg.Command)
w := worker.NewWorker(time.Millisecond*300, func() {
SendAll(Message{Type: MessageTypeCommand, Command: cmd})
})
go w.Start()
go cmd.Run(func() {
w.Close()
SendAll(Message{Type: MessageTypeCommand, Command: cmd})
})
break
} }
} }

View File

@ -3,14 +3,15 @@ package websocket
import "github.com/FreifunkBremen/freifunkmanager/runtime" import "github.com/FreifunkBremen/freifunkmanager/runtime"
type Message struct { type Message struct {
Type string `json:"type"` Type string `json:"type"`
Body interface{} `json:"body,omitempty"` Body interface{} `json:"body,omitempty"`
Node *runtime.Node `json:"node,omitempty"` Node *runtime.Node `json:"node,omitempty"`
Command *runtime.Command `json:"cmd,omitempty"`
} }
const ( const (
MessageTypeSystemNode = "system" MessageTypeSystemNode = "system"
MessageTypeCurrentNode = "current" MessageTypeCurrentNode = "current"
MessageTypeStats = "stats" MessageTypeStats = "stats"
MessageTypeCmd = "cmd" MessageTypeCommand = "cmd"
) )

View File

@ -16,9 +16,11 @@ var nodes *runtime.Nodes
var clients map[string]*Client var clients map[string]*Client
var clientsMutex sync.Mutex var clientsMutex sync.Mutex
var stats *runtimeYanic.GlobalStats var stats *runtimeYanic.GlobalStats
var commands *runtime.Commands
func Start(nodeBind *runtime.Nodes) { func Start(nodeBind *runtime.Nodes, commandsBind *runtime.Commands) {
nodes = nodeBind nodes = nodeBind
commands = commandsBind
clients = make(map[string]*Client) clients = make(map[string]*Client)
http.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) { http.Handle("/websocket", websocket.Handler(func(ws *websocket.Conn) {

View File

@ -10,8 +10,9 @@ import (
func TestStart(t *testing.T) { func TestStart(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
nodes := &runtime.Nodes{} nodes := &runtime.Nodes{}
commands := &runtime.Commands{}
assert.Nil(clients) assert.Nil(clients)
Start(nodes) Start(nodes, commands)
assert.NotNil(clients) assert.NotNil(clients)
Close() Close()
} }