From 4d3a860604843469a7cf4814f82c97d841a3e4e2 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Wed, 19 Aug 2020 18:58:48 -0700 Subject: [PATCH] Use environment namespace for power state, don't duplicate them across server --- cmd/root.go | 2 +- environment/docker/container.go | 7 +++---- environment/docker/power.go | 26 +++++++++++++------------- environment/docker/state.go | 9 ++++----- environment/docker/stats.go | 5 ++--- environment/environment.go | 7 +++++++ router/websocket/websocket.go | 5 +++-- server/crash.go | 3 ++- server/install.go | 6 +++--- server/listeners.go | 6 +++--- server/state.go | 20 ++++++++------------ server/update.go | 3 ++- system/const.go | 7 ------- 13 files changed, 51 insertions(+), 55 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 42c240d..a4ef06d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -208,7 +208,7 @@ func rootCmdRun(*cobra.Command, []string) { // Addresses potentially invalid data in the stored file that can cause Wings to lose // track of what the actual server state is. - _ = s.SetState(server.ProcessOfflineState) + _ = s.SetState(environment.ProcessOfflineState) }) } diff --git a/environment/docker/container.go b/environment/docker/container.go index c3065c5..96ed9c7 100644 --- a/environment/docker/container.go +++ b/environment/docker/container.go @@ -13,7 +13,6 @@ import ( "github.com/pkg/errors" "github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/environment" - "github.com/pterodactyl/wings/system" "io" "strconv" "strings" @@ -54,7 +53,7 @@ func (e *Environment) Attach() error { defer cancel() defer e.stream.Close() defer func() { - e.setState(system.ProcessOfflineState) + e.setState(environment.ProcessOfflineState) e.SetStream(nil) }() @@ -230,7 +229,7 @@ func (e *Environment) convertMounts() []mount.Mount { // it will be forcibly stopped by Docker. func (e *Environment) Destroy() error { // We set it to stopping than offline to prevent crash detection from being triggeree. - e.setState(system.ProcessStoppingState) + e.setState(environment.ProcessStoppingState) err := e.client.ContainerRemove(context.Background(), e.Id, types.ContainerRemoveOptions{ RemoveVolumes: true, @@ -246,7 +245,7 @@ func (e *Environment) Destroy() error { return nil } - e.setState(system.ProcessOfflineState) + e.setState(environment.ProcessOfflineState) return err } diff --git a/environment/docker/power.go b/environment/docker/power.go index 72efddc..d691b4e 100644 --- a/environment/docker/power.go +++ b/environment/docker/power.go @@ -8,7 +8,7 @@ import ( "github.com/docker/docker/client" "github.com/pkg/errors" "github.com/pterodactyl/wings/api" - "github.com/pterodactyl/wings/system" + "github.com/pterodactyl/wings/environment" "os" "strings" "time" @@ -57,8 +57,8 @@ func (e *Environment) Start() error { // If we don't set it to stopping first, you'll trigger crash detection which // we don't want to do at this point since it'll just immediately try to do the // exact same action that lead to it crashing in the first place... - e.setState(system.ProcessStoppingState) - e.setState(system.ProcessOfflineState) + e.setState(environment.ProcessStoppingState) + e.setState(environment.ProcessOfflineState) } }() @@ -74,7 +74,7 @@ func (e *Environment) Start() error { } else { // If the server is running update our internal state and continue on with the attach. if c.State.Running { - e.setState(system.ProcessRunningState) + e.setState(environment.ProcessRunningState) return e.Attach() } @@ -89,7 +89,7 @@ func (e *Environment) Start() error { } } - e.setState(system.ProcessStartingState) + e.setState(environment.ProcessStartingState) // Set this to true for now, we will set it to false once we reach the // end of this chain. @@ -136,8 +136,8 @@ func (e *Environment) Stop() error { // If the process is already offline don't switch it back to stopping. Just leave it how // it is and continue through to the stop handling for the process. - if e.State() != system.ProcessOfflineState { - e.setState(system.ProcessStoppingState) + if e.State() != environment.ProcessOfflineState { + e.setState(environment.ProcessStoppingState) } // Only attempt to send the stop command to the instance if we are actually attached to @@ -153,7 +153,7 @@ func (e *Environment) Stop() error { // an error. if client.IsErrNotFound(err) { e.SetStream(nil) - e.setState(system.ProcessOfflineState) + e.setState(environment.ProcessOfflineState) return nil } @@ -209,16 +209,16 @@ func (e *Environment) Terminate(signal os.Signal) error { // If the container is not running but we're not already in a stopped state go ahead // and update things to indicate we should be completely stopped now. Set to stopping // first so crash detection is not triggered. - if e.State() != system.ProcessOfflineState { - e.setState(system.ProcessStoppingState) - e.setState(system.ProcessOfflineState) + if e.State() != environment.ProcessOfflineState { + e.setState(environment.ProcessStoppingState) + e.setState(environment.ProcessOfflineState) } return nil } // We set it to stopping than offline to prevent crash detection from being triggeree. - e.setState(system.ProcessStoppingState) + e.setState(environment.ProcessStoppingState) sig := strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed") @@ -226,7 +226,7 @@ func (e *Environment) Terminate(signal os.Signal) error { return err } - e.setState(system.ProcessOfflineState) + e.setState(environment.ProcessOfflineState) return nil } diff --git a/environment/docker/state.go b/environment/docker/state.go index a87e443..44bf25b 100644 --- a/environment/docker/state.go +++ b/environment/docker/state.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/pkg/errors" "github.com/pterodactyl/wings/environment" - "github.com/pterodactyl/wings/system" ) // Returns the current environment state. @@ -18,10 +17,10 @@ func (e *Environment) State() string { // Sets the state of the environment. This emits an event that server's can hook into to // take their own actions and track their own state based on the environment. func (e *Environment) setState(state string) error { - if state != system.ProcessOfflineState && - state != system.ProcessStartingState && - state != system.ProcessRunningState && - state != system.ProcessStoppingState { + if state != environment.ProcessOfflineState && + state != environment.ProcessStartingState && + state != environment.ProcessRunningState && + state != environment.ProcessStoppingState { return errors.New(fmt.Sprintf("invalid server state received: %s", state)) } diff --git a/environment/docker/stats.go b/environment/docker/stats.go index 7dfd82e..bd3f79b 100644 --- a/environment/docker/stats.go +++ b/environment/docker/stats.go @@ -7,7 +7,6 @@ import ( "github.com/docker/docker/api/types" "github.com/pkg/errors" "github.com/pterodactyl/wings/environment" - "github.com/pterodactyl/wings/system" "io" "math" "sync/atomic" @@ -16,7 +15,7 @@ import ( // Attach to the instance and then automatically emit an event whenever the resource usage for the // server process changes. func (e *Environment) pollResources(ctx context.Context) error { - if e.State() == system.ProcessOfflineState { + if e.State() == environment.ProcessOfflineState { return errors.New("attempting to enable resource polling on a stopped server instance") } @@ -43,7 +42,7 @@ func (e *Environment) pollResources(ctx context.Context) error { } // Disable collection if the server is in an offline state and this process is still running. - if e.State() == system.ProcessOfflineState { + if e.State() == environment.ProcessOfflineState { return nil } diff --git a/environment/environment.go b/environment/environment.go index 085a8ac..c80d5d4 100644 --- a/environment/environment.go +++ b/environment/environment.go @@ -11,6 +11,13 @@ const ( ResourceEvent = "resources" ) +const ( + ProcessOfflineState = "offline" + ProcessStartingState = "starting" + ProcessRunningState = "running" + ProcessStoppingState = "stopping" +) + // Defines the basic interface that all environments need to implement so that // a server can be properly controlled. type ProcessEnvironment interface { diff --git a/router/websocket/websocket.go b/router/websocket/websocket.go index 7bca972..3ed2fa0 100644 --- a/router/websocket/websocket.go +++ b/router/websocket/websocket.go @@ -10,6 +10,7 @@ import ( "github.com/gorilla/websocket" "github.com/pkg/errors" "github.com/pterodactyl/wings/config" + "github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/router/tokens" "github.com/pterodactyl/wings/server" "net/http" @@ -259,7 +260,7 @@ func (h *Handler) HandleInbound(m Message) error { // Only send the current disk usage if the server is offline, if docker container is running, // Environment#EnableResourcePolling() will send this data to all clients. - if state == server.ProcessOfflineState { + if state == environment.ProcessOfflineState { _ = h.server.Filesystem.HasSpaceAvailable() b, _ := json.Marshal(h.server.Proc()) @@ -328,7 +329,7 @@ func (h *Handler) HandleInbound(m Message) error { return nil } - if h.server.GetState() == server.ProcessOfflineState { + if h.server.GetState() == environment.ProcessOfflineState { return nil } diff --git a/server/crash.go b/server/crash.go index 66ec98a..08470e5 100644 --- a/server/crash.go +++ b/server/crash.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/pkg/errors" "github.com/pterodactyl/wings/config" + "github.com/pterodactyl/wings/environment" "sync" "time" ) @@ -44,7 +45,7 @@ func (s *Server) handleServerCrash() error { // No point in doing anything here if the server isn't currently offline, there // is no reason to do a crash detection event. If the server crash detection is // disabled we want to skip anything after this as well. - if s.GetState() != ProcessOfflineState || !s.Config().CrashDetectionEnabled { + if s.GetState() != environment.ProcessOfflineState || !s.Config().CrashDetectionEnabled { if !s.Config().CrashDetectionEnabled { s.Log().Debug("server triggered crash detection but handler is disabled for server process") diff --git a/server/install.go b/server/install.go index a4f5090..9aea719 100644 --- a/server/install.go +++ b/server/install.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/config" + "github.com/pterodactyl/wings/environment" "golang.org/x/sync/semaphore" "html/template" "io" @@ -58,9 +59,8 @@ func (s *Server) Install(sync bool) error { // Some how these publish events are sent to clients in reverse order, // this is probably due to channels having the most recently sent item first. - // Ensure that the server is marked as offline. - s.Events().Publish(StatusEvent, ProcessOfflineState) + s.Events().Publish(StatusEvent, environment.ProcessOfflineState) // Push an event to the websocket so we can auto-refresh the information in the panel once // the install is completed. @@ -72,7 +72,7 @@ func (s *Server) Install(sync bool) error { // Reinstalls a server's software by utilizing the install script for the server egg. This // does not touch any existing files for the server, other than what the script modifies. func (s *Server) Reinstall() error { - if s.GetState() != ProcessOfflineState { + if s.GetState() != environment.ProcessOfflineState { s.Log().Debug("waiting for server instance to enter a stopped state") if err := s.Environment.WaitForStop(10, true); err != nil { return err diff --git a/server/listeners.go b/server/listeners.go index 1bd4d07..675af39 100644 --- a/server/listeners.go +++ b/server/listeners.go @@ -66,7 +66,7 @@ func (s *Server) onConsoleOutput(data string) { processConfiguration := s.ProcessConfiguration() // Check if the server is currently starting. - if s.GetState() == ProcessStartingState { + if s.GetState() == environment.ProcessStartingState { // Check if we should strip ansi color codes. if processConfiguration.Startup.StripAnsi { // Strip ansi color codes from the data string. @@ -87,7 +87,7 @@ func (s *Server) onConsoleOutput(data string) { // If the specific line of output is one that would mark the server as started, // set the server to that state. Only do this if the server is not currently stopped // or stopping. - _ = s.SetState(ProcessRunningState) + _ = s.SetState(environment.ProcessRunningState) break } } @@ -99,7 +99,7 @@ func (s *Server) onConsoleOutput(data string) { stop := processConfiguration.Stop if stop.Type == api.ProcessStopCommand && data == stop.Value { - _ = s.SetState(ProcessStoppingState) + _ = s.SetState(environment.ProcessOfflineState) } } } diff --git a/server/state.go b/server/state.go index b978520..81d42a4 100644 --- a/server/state.go +++ b/server/state.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/pkg/errors" "github.com/pterodactyl/wings/config" - "github.com/pterodactyl/wings/system" + "github.com/pterodactyl/wings/environment" "io" "io/ioutil" "os" @@ -14,13 +14,6 @@ import ( var stateMutex sync.Mutex -const ( - ProcessOfflineState = "offline" - ProcessStartingState = "starting" - ProcessRunningState = "running" - ProcessStoppingState = "stopping" -) - // Returns the state of the servers. func getServerStates() (map[string]string, error) { // Request a lock after we check if the file exists. @@ -71,7 +64,10 @@ func saveServerStates() error { // 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 { - if state != ProcessOfflineState && state != ProcessStartingState && state != ProcessRunningState && state != ProcessStoppingState { + if state != environment.ProcessOfflineState && + state != environment.ProcessStartingState && + state != environment.ProcessRunningState && + state != environment.ProcessStoppingState { return errors.New(fmt.Sprintf("invalid server state received: %s", state)) } @@ -102,7 +98,7 @@ func (s *Server) SetState(state string) error { // Reset the resource usage to 0 when the process fully stops so that all of the UI // views in the Panel correctly display 0. - if state == system.ProcessOfflineState { + if state == environment.ProcessOfflineState { s.resources.mu.Lock() s.resources.Empty() s.resources.mu.Unlock() @@ -118,7 +114,7 @@ func (s *Server) SetState(state string) error { // automatically attempt to start the process back up for the user. This is done in a // separate thread as to not block any actions currently taking place in the flow // that called this function. - if (prevState == ProcessStartingState || prevState == ProcessRunningState) && s.GetState() == ProcessOfflineState { + if (prevState == environment.ProcessStartingState || prevState == environment.ProcessRunningState) && s.GetState() == environment.ProcessOfflineState { s.Log().Info("detected server as entering a crashed state; running crash handler") go func(server *Server) { @@ -146,5 +142,5 @@ func (s *Server) GetState() string { func (s *Server) IsRunning() bool { st := s.GetState() - return st == ProcessRunningState || st == ProcessStartingState + return st == environment.ProcessRunningState || st == environment.ProcessStartingState } diff --git a/server/update.go b/server/update.go index b412c15..c9a6d8c 100644 --- a/server/update.go +++ b/server/update.go @@ -5,6 +5,7 @@ import ( "github.com/buger/jsonparser" "github.com/imdario/mergo" "github.com/pkg/errors" + "github.com/pterodactyl/wings/environment" ) // Merges data passed through in JSON form into the existing server object. @@ -112,7 +113,7 @@ func (s *Server) UpdateDataStructure(data []byte, background bool) error { func (s *Server) runBackgroundActions() { // Check if the s is now suspended, and if so and the process is not terminated // yet, do it immediately. - if s.IsSuspended() && s.GetState() != ProcessOfflineState { + if s.IsSuspended() && s.GetState() != environment.ProcessOfflineState { s.Log().Info("server suspended with running process state, terminating now") if err := s.Environment.WaitForStop(10, true); err != nil { diff --git a/system/const.go b/system/const.go index 28a7a58..87d87fb 100644 --- a/system/const.go +++ b/system/const.go @@ -4,10 +4,3 @@ var ( // The current version of this software. Version = "0.0.1" ) - -const ( - ProcessOfflineState = "offline" - ProcessStartingState = "starting" - ProcessRunningState = "running" - ProcessStoppingState = "stopping" -) \ No newline at end of file