Emit server status events

This commit is contained in:
Dane Everitt
2019-04-21 12:02:28 -07:00
parent bed30d9229
commit 8795e7d739
4 changed files with 70 additions and 39 deletions

View File

@@ -120,6 +120,7 @@ func (d *DockerEnvironment) Start() error {
// No reason to try starting a container that is already running.
if c.State.Running {
d.Server.Emit(StatusEvent, ProcessRunningState)
if !d.attached {
return d.Attach()
}
@@ -129,7 +130,9 @@ func (d *DockerEnvironment) Start() error {
opts := types.ContainerStartOptions{}
d.Server.Emit(StatusEvent, ProcessStartingState)
if err := d.Client.ContainerStart(context.Background(), d.Server.Uuid, opts); err != nil {
d.Server.Emit(StatusEvent, ProcessOfflineState)
return err
}
@@ -142,6 +145,7 @@ func (d *DockerEnvironment) Start() error {
func (d *DockerEnvironment) Stop() error {
t := time.Second * 10
d.Server.Emit(StatusEvent, ProcessStoppingState)
return d.Client.ContainerStop(context.Background(), d.Server.Uuid, &t)
}
@@ -158,6 +162,7 @@ func (d *DockerEnvironment) Terminate(signal os.Signal) error {
return nil
}
d.Server.Emit(StatusEvent, ProcessStoppingState)
return d.Client.ContainerKill(ctx, d.Server.Uuid, signal.String())
}
@@ -193,6 +198,7 @@ func (d *DockerEnvironment) Attach() error {
go func() {
defer d.stream.Close()
defer func() {
d.Server.Emit(StatusEvent, ProcessOfflineState)
d.attached = false
}()
@@ -232,7 +238,7 @@ func (d *DockerEnvironment) FollowConsoleOutput() error {
}
if err := s.Err(); err != nil {
zap.S().Errorw("error in scanner", zap.Error(err))
zap.S().Warnw("error processing scanner line in console output", zap.String("server", d.Server.Uuid), zap.Error(err))
}
}(reader)

View File

@@ -7,6 +7,7 @@ type EventListenerFunction *func(string)
// Defines all of the possible output events for a server.
const (
ConsoleOutputEvent = "console"
StatusEvent = "status"
)
// Adds an event listener for the server instance.

View File

@@ -1,8 +1,9 @@
package server
import (
"errors"
"fmt"
"github.com/patrickmn/go-cache"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config"
"github.com/remeh/sizedwaitgroup"
"go.uber.org/zap"
@@ -14,16 +15,6 @@ import (
"time"
)
// Defines states that identify if the server is running or not.
const (
StateOffline = "off"
StateStarting = "starting"
StateRunning = "running"
StateStopping = "stopping"
)
type ProcessState string
// High level definition for a server instance being controlled by Wings.
type Server struct {
// The unique identifier for the server that should be used when referencing
@@ -36,7 +27,7 @@ type Server struct {
Suspended bool `json:"suspended"`
// The power state of the server.
State ProcessState `json:"state"`
State string `json:"state"`
// The command that should be used when booting up the server instance.
Invocation string `json:"invocation"`
@@ -190,7 +181,7 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, e
return nil, err
}
withConfiguration := func (e *DockerEnvironment) {
withConfiguration := func(e *DockerEnvironment) {
e.User = cfg.User.Uid
e.TimezonePath = cfg.TimezonePath
e.Server = s
@@ -207,7 +198,7 @@ func FromConfiguration(data []byte, cfg *config.SystemConfiguration) (*Server, e
}
s.Environment = env
s.Cache = cache.New(time.Minute * 10, time.Minute * 15)
s.Cache = cache.New(time.Minute*10, time.Minute*15)
s.Filesystem = &Filesystem{
Root: cfg.Data,
Server: s,
@@ -221,22 +212,6 @@ func (s *Server) ReadLogfile(len int64) ([]string, error) {
return s.Environment.Readlog(len)
}
// Sets the state of the server process.
func (s *Server) SetState(state ProcessState) error {
switch state {
case StateOffline:
case StateRunning:
case StateStarting:
case StateStopping:
s.State = state
break
default:
return errors.New("invalid state provided")
}
return nil
}
// Determine if the server is bootable in it's current state or not. This will not
// indicate why a server is not bootable, only if it is.
func (s *Server) IsBootable() bool {
@@ -249,4 +224,35 @@ func (s *Server) IsBootable() bool {
// for the server is setup, and that all of the necessary files are created.
func (s *Server) CreateEnvironment() error {
return s.Environment.Create()
}
}
const (
ProcessOfflineState = "offline"
ProcessStartingState = "starting"
ProcessRunningState = "running"
ProcessStoppingState = "stopping"
)
// Sets the state of the server internally. This function handles crash detection as
// well as reporting to event listeners for the server.
func (s *Server) SetState(state string) error {
switch state {
case ProcessOfflineState:
case ProcessStartingState:
case ProcessRunningState:
case ProcessStoppingState:
s.State = state
break
default:
return errors.New(fmt.Sprintf("invalid server state received: %s", state))
}
// Emit the event to any listeners that are currently registered.
s.Emit(StatusEvent, state)
// @todo handle a crash event here. Need to port the logic from the Nodejs daemon
// into this daemon. I believe its basically just if state != stopping && newState = stopped
// then crashed.
return nil
}