Set session host
Add ping to L2 router
This commit is contained in:
@@ -20,7 +20,7 @@ const (
|
||||
var NameFilter = regexp.MustCompile(PWDHostPortGroupRegex)
|
||||
var AliasFilter = regexp.MustCompile(AliasPortGroupRegex)
|
||||
|
||||
var SSLPortNumber, PortNumber, Key, Cert, SessionsFile, PWDContainerName, L2ContainerName, L2Subdomain, PWDCName, HashKey, SSHKeyPath string
|
||||
var SSLPortNumber, PortNumber, Key, Cert, SessionsFile, PWDContainerName, L2ContainerName, L2Subdomain, PWDCName, HashKey, SSHKeyPath, L2RouterIP string
|
||||
var MaxLoadAvg float64
|
||||
|
||||
func ParseFlags() {
|
||||
@@ -31,6 +31,7 @@ func ParseFlags() {
|
||||
flag.StringVar(&SessionsFile, "save", "./pwd/sessions", "Tell where to store sessions file")
|
||||
flag.StringVar(&PWDContainerName, "name", "pwd", "Container name used to run PWD (used to be able to connect it to the networks it creates)")
|
||||
flag.StringVar(&L2ContainerName, "l2", "l2", "Container name used to run L2 Router")
|
||||
flag.StringVar(&L2RouterIP, "l2-ip", "", "Host IP address for L2 router ping response")
|
||||
flag.StringVar(&L2Subdomain, "l2-subdomain", "direct", "Subdomain to the L2 Router")
|
||||
flag.StringVar(&PWDCName, "cname", "", "CNAME given to this host")
|
||||
flag.StringVar(&HashKey, "hash_key", "salmonrosado", "Hash key to use for cookies")
|
||||
|
||||
@@ -33,6 +33,7 @@ type DockerApi interface {
|
||||
CreateNetwork(id string) error
|
||||
ConnectNetwork(container, network, ip string) (string, error)
|
||||
GetDaemonInfo() (types.Info, error)
|
||||
GetDaemonHost() string
|
||||
GetSwarmPorts() ([]string, []uint16, error)
|
||||
GetPorts() ([]uint16, error)
|
||||
GetContainerStats(name string) (io.ReadCloser, error)
|
||||
@@ -102,6 +103,10 @@ func (d *docker) GetDaemonInfo() (types.Info, error) {
|
||||
return d.c.Info(context.Background())
|
||||
}
|
||||
|
||||
func (d *docker) GetDaemonHost() string {
|
||||
return d.c.DaemonHost()
|
||||
}
|
||||
|
||||
func (d *docker) GetSwarmPorts() ([]string, []uint16, error) {
|
||||
hosts := []string{}
|
||||
ports := []uint16{}
|
||||
|
||||
@@ -28,6 +28,11 @@ func (m *Mock) GetDaemonInfo() (types.Info, error) {
|
||||
return args.Get(0).(types.Info), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *Mock) GetDaemonHost() string {
|
||||
args := m.Called()
|
||||
return args.String(0)
|
||||
}
|
||||
|
||||
func (m *Mock) GetSwarmPorts() ([]string, []uint16, error) {
|
||||
args := m.Called()
|
||||
return args.Get(0).([]string), args.Get(1).([]uint16), args.Error(2)
|
||||
|
||||
@@ -1,23 +1,6 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/play-with-docker/play-with-docker/config"
|
||||
"github.com/shirou/gopsutil/load"
|
||||
)
|
||||
import "net/http"
|
||||
|
||||
func Ping(rw http.ResponseWriter, req *http.Request) {
|
||||
// Get system load average of the last 5 minutes and compare it against a threashold.
|
||||
|
||||
a, err := load.Avg()
|
||||
if err != nil {
|
||||
log.Println("Cannot get system load average!", err)
|
||||
} else {
|
||||
if a.Load5 > config.MaxLoadAvg {
|
||||
log.Printf("System load average is too high [%f]\n", a.Load5)
|
||||
rw.WriteHeader(http.StatusInsufficientStorage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ func TestClientNew(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
@@ -59,6 +60,7 @@ func TestClientCount(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
@@ -93,6 +95,7 @@ func TestClientResizeViewPort(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
|
||||
@@ -47,6 +47,7 @@ func TestInstanceNew(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
@@ -69,6 +70,7 @@ func TestInstanceNew(t *testing.T) {
|
||||
IsDockerHost: true,
|
||||
SessionId: session.Id,
|
||||
Session: session,
|
||||
SessionHost: session.Host,
|
||||
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
||||
}
|
||||
expectedContainerOpts := docker.CreateContainerOpts{
|
||||
@@ -109,6 +111,7 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
@@ -132,6 +135,7 @@ func TestInstanceNew_WithNotAllowedImage(t *testing.T) {
|
||||
SessionId: session.Id,
|
||||
IsDockerHost: false,
|
||||
Session: session,
|
||||
SessionHost: session.Host,
|
||||
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
||||
}
|
||||
expectedContainerOpts := docker.CreateContainerOpts{
|
||||
@@ -171,6 +175,7 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
@@ -192,6 +197,7 @@ func TestInstanceNew_WithCustomHostname(t *testing.T) {
|
||||
Image: "redis",
|
||||
IsDockerHost: false,
|
||||
Session: session,
|
||||
SessionHost: session.Host,
|
||||
SessionId: session.Id,
|
||||
ProxyHost: router.EncodeHost(session.Id, "10.0.0.1", router.HostOpts{}),
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -61,15 +62,28 @@ func (p *pwd) SessionNew(duration time.Duration, stack, stackName, imageName str
|
||||
|
||||
log.Printf("NewSession id=[%s]\n", s.Id)
|
||||
|
||||
if err := p.docker(s.Id).CreateNetwork(s.Id); err != nil {
|
||||
dockerClient := p.docker(s.Id)
|
||||
u, _ := url.Parse(dockerClient.GetDaemonHost())
|
||||
if u.Host == "" {
|
||||
s.Host = "localhost"
|
||||
} else {
|
||||
chunks := strings.Split(u.Host, ":")
|
||||
s.Host = chunks[0]
|
||||
}
|
||||
|
||||
if err := dockerClient.CreateNetwork(s.Id); err != nil {
|
||||
log.Println("ERROR NETWORKING")
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("Network [%s] created for session [%s]\n", s.Id, s.Id)
|
||||
|
||||
if err := p.connectToNetwork(s); err != nil {
|
||||
ip, err := dockerClient.ConnectNetwork(config.L2ContainerName, s.Id, s.PwdIpAddress)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
s.PwdIpAddress = ip
|
||||
log.Printf("Connected %s to network [%s]\n", config.PWDContainerName, s.Id)
|
||||
|
||||
if err := p.storage.SessionPut(s); err != nil {
|
||||
log.Println(err)
|
||||
@@ -278,42 +292,3 @@ func (p *pwd) SessionSetup(session *types.Session, conf SessionSetupConf) error
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
// This function should be called any time a session needs to be prepared:
|
||||
// 1. Like when it is created
|
||||
// 2. When it was loaded from storage
|
||||
func (p *pwd) prepareSession(session *types.Session) (bool, error) {
|
||||
session.Lock()
|
||||
defer session.Unlock()
|
||||
|
||||
if isSessionPrepared(session.Id) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Connect PWD daemon to the new network
|
||||
if err := p.connectToNetwork(session); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, i := range session.Instances {
|
||||
// wire the session back to the instance
|
||||
i.Session = session
|
||||
go p.InstanceAttachTerminal(i)
|
||||
}
|
||||
preparedSessions[session.Id] = true
|
||||
|
||||
return true, nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (p *pwd) connectToNetwork(s *types.Session) error {
|
||||
ip, err := p.docker(s.Id).ConnectNetwork(config.L2ContainerName, s.Id, s.PwdIpAddress)
|
||||
if err != nil {
|
||||
log.Println("ERROR NETWORKING")
|
||||
return err
|
||||
}
|
||||
s.PwdIpAddress = ip
|
||||
log.Printf("Connected %s to network [%s]\n", config.PWDContainerName, s.Id)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ func TestSessionNew(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
@@ -53,6 +54,7 @@ func TestSessionNew(t *testing.T) {
|
||||
assert.Equal(t, "stackPath", s.Stack)
|
||||
assert.Equal(t, "stackName", s.StackName)
|
||||
assert.Equal(t, "imageName", s.ImageName)
|
||||
assert.Equal(t, "localhost", s.Host)
|
||||
assert.False(t, s.Ready)
|
||||
|
||||
assert.Equal(t, "10.0.0.1", s.PwdIpAddress)
|
||||
@@ -74,13 +76,14 @@ func TestSessionSetup(t *testing.T) {
|
||||
_g.On("NewId").Return("aaaabbbbcccc")
|
||||
_f.On("GetForSession", "aaaabbbbcccc").Return(_d, nil)
|
||||
_d.On("CreateNetwork", "aaaabbbbcccc").Return(nil)
|
||||
_d.On("GetDaemonHost").Return("localhost")
|
||||
_d.On("ConnectNetwork", config.L2ContainerName, "aaaabbbbcccc", "").Return("10.0.0.1", nil)
|
||||
_s.On("SessionPut", mock.AnythingOfType("*types.Session")).Return(nil)
|
||||
_s.On("InstanceCreate", "aaaabbbbcccc", mock.AnythingOfType("*types.Instance")).Return(nil)
|
||||
_s.On("SessionCount").Return(1, nil)
|
||||
_s.On("InstanceCount").Return(0, nil)
|
||||
|
||||
_d.On("CreateContainer", docker.CreateContainerOpts{Image: "franela/dind", SessionId: "aaaabbbbcccc", PwdIpAddress: "10.0.0.1", ContainerName: "aaaabbbb_manager1", Hostname: "manager1", Privileged: true}).Return("10.0.0.2", nil)
|
||||
_d.On("CreateContainer", docker.CreateContainerOpts{Image: "franela/dind", SessionId: "aaaabbbbcccc", PwdIpAddress: "10.0.0.1", ContainerName: "aaaabbbb_manager1", Hostname: "manager1", Privileged: true, HostFQDN: "localhost"}).Return("10.0.0.2", nil)
|
||||
_f.On("GetForInstance", "aaaabbbbcccc", "aaaabbbb_manager1").Return(_d, nil)
|
||||
_d.On("SwarmInit").Return(&docker.SwarmTokens{Manager: "managerToken", Worker: "workerToken"}, nil)
|
||||
_e.M.On("Emit", event.INSTANCE_NEW, "aaaabbbbcccc", []interface{}{"aaaabbbb_manager1", "10.0.0.2", "manager1"}).Return()
|
||||
|
||||
@@ -6,14 +6,19 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/play-with-docker/play-with-docker/config"
|
||||
"github.com/play-with-docker/play-with-docker/router"
|
||||
"github.com/shirou/gopsutil/load"
|
||||
"github.com/urfave/negroni"
|
||||
)
|
||||
|
||||
func director(protocol router.Protocol, host string) (*net.TCPAddr, error) {
|
||||
@@ -128,7 +133,36 @@ func main() {
|
||||
}
|
||||
go monitorNetworks()
|
||||
|
||||
ro := mux.NewRouter()
|
||||
ro.HandleFunc("/ping", ping).Methods("GET")
|
||||
n := negroni.Classic()
|
||||
n.UseHandler(ro)
|
||||
|
||||
httpServer := http.Server{
|
||||
Addr: "0.0.0.0:8080",
|
||||
Handler: n,
|
||||
IdleTimeout: 30 * time.Second,
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
}
|
||||
go httpServer.ListenAndServe()
|
||||
|
||||
r := router.NewRouter(director, config.SSHKeyPath)
|
||||
r.ListenAndWait(":443", ":53", ":22")
|
||||
defer r.Close()
|
||||
}
|
||||
|
||||
func ping(rw http.ResponseWriter, req *http.Request) {
|
||||
// Get system load average of the last 5 minutes and compare it against a threashold.
|
||||
|
||||
a, err := load.Avg()
|
||||
if err != nil {
|
||||
log.Println("Cannot get system load average!", err)
|
||||
} else {
|
||||
if a.Load5 > config.MaxLoadAvg {
|
||||
log.Printf("System load average is too high [%f]\n", a.Load5)
|
||||
rw.WriteHeader(http.StatusInsufficientStorage)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(rw, `{"ip": "%s"}`, config.L2RouterIP)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user