dospin/servermanager.go

166 lines
3.6 KiB
Go
Raw Normal View History

2016-02-27 16:21:49 -06:00
/*
2017-01-25 17:59:25 -06:00
Copyright 2016-2017 gtalent2@gmail.com
2016-02-27 16:21:49 -06:00
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
2016-02-27 16:10:44 -06:00
package main
import (
"log"
"net"
"strconv"
)
2016-02-27 16:10:44 -06:00
const (
SERVERMANAGER_SPINUP = iota
SERVERMANAGER_SPINDOWN
SERVERMANAGER_STOP
)
type serverManagerEvent struct {
eventType int
tcpConn *net.TCPConn
}
type ServerHandler interface {
// Takes snapshot name, and returns the IP to connect to.
Spinup(name string) (string, error)
Spindown(name string) error
}
2016-02-27 16:10:44 -06:00
type ServerManager struct {
name string
ports []int
in chan serverManagerEvent
done chan interface{}
2016-02-27 16:10:44 -06:00
usageScore int // spin down server when this reaches 0
server ServerHandler
}
func NewServerManager(name string, server ServerHandler, settings Settings) *ServerManager {
sm := new(ServerManager)
sm.name = name
2016-02-28 01:03:16 -06:00
sm.ports = settings.Servers[name].Ports
sm.in = make(chan serverManagerEvent)
sm.done = make(chan interface{})
2016-02-27 16:10:44 -06:00
sm.usageScore = 5
sm.server = server
return sm
}
/*
Serves channel requests.
*/
func (me *ServerManager) Serve() {
// TODO: see if server is currently up, and setup port forwarding if so
// event loop
2016-02-27 16:10:44 -06:00
for running := true; running; {
select {
case action := <-me.in:
running = me.serveAction(action)
}
}
// notify done
me.done <- 42
2016-02-27 16:10:44 -06:00
}
/*
Sends the serve loop a spinup message.
*/
func (me *ServerManager) Spinup(c *net.TCPConn) {
me.in <- serverManagerEvent{eventType: SERVERMANAGER_SPINUP, tcpConn: c}
2016-02-27 16:10:44 -06:00
}
/*
Sends the serve loop a spindown message.
*/
func (me *ServerManager) Spindown(c *net.TCPConn) {
me.in <- serverManagerEvent{eventType: SERVERMANAGER_SPINDOWN}
2016-02-27 16:10:44 -06:00
}
/*
Sends the serve loop a quit message.
*/
func (me *ServerManager) Stop() {
me.in <- serverManagerEvent{eventType: SERVERMANAGER_STOP}
2016-02-27 16:10:44 -06:00
}
func (me *ServerManager) Done() {
<-me.done
}
func (me *ServerManager) addPortForwards(localIp, remoteIp string) {
log.Println("Ports:", me.ports)
for _, p := range me.ports {
port := strconv.Itoa(p)
2017-01-26 20:04:33 -06:00
addPortForward(me.name, localIp, remoteIp, port)
}
2016-02-27 16:10:44 -06:00
}
func (me *ServerManager) rmPortForwards() {
rmPortForward(me.name)
2016-02-27 16:10:44 -06:00
}
func (me *ServerManager) setupListener(port int) {
portStr := strconv.Itoa(port)
addr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:"+portStr)
if err != nil {
log.Print("Could not resolve port and listen address:", err)
return
}
// listen on port
go func() {
l, err := net.ListenTCP("tcp", addr)
if err != nil {
log.Print("Could not listen for TCP connection:", err)
} else {
for {
conn, err := l.AcceptTCP()
if err != nil {
log.Print("Could not accept TCP connection:", err)
} else {
// connection accepted
// spinup machine
me.Spinup(conn)
// close existing connection, not doing anything with it
conn.Close()
}
}
}
}()
}
func (me *ServerManager) serveAction(event serverManagerEvent) bool {
2016-02-27 16:10:44 -06:00
running := true
switch event.eventType {
2016-02-27 16:10:44 -06:00
case SERVERMANAGER_SPINUP:
targetIp, err := me.server.Spinup(me.name)
if err == nil {
log.Println("ServerManager: Got IP for", me.name+":", targetIp)
localIp := event.tcpConn.LocalAddr().String()
me.addPortForwards(localIp, targetIp)
} else {
2016-02-27 16:10:44 -06:00
log.Println("ServerManager: Could not spin up "+me.name+":", err)
}
case SERVERMANAGER_SPINDOWN:
err := me.server.Spindown(me.name)
if err == nil {
me.rmPortForwards()
} else {
2016-02-27 16:10:44 -06:00
log.Println("ServerManager: Could not spin down "+me.name+":", err)
}
case SERVERMANAGER_STOP:
running = false
}
return running
}