diff --git a/environment/docker/power.go b/environment/docker/power.go index 8bc1ffd..d08076d 100644 --- a/environment/docker/power.go +++ b/environment/docker/power.go @@ -128,29 +128,6 @@ func (e *Environment) Start() error { return e.Attach() } -// Restarts the server process by waiting for the process to gracefully stop and then triggering a -// start command. This works identially to how -func (e *Environment) Restart(seconds uint, terminate bool) error { - // Only try to wait for stop if the process is currently running, otherwise just skip right to the - // start event. - if r, _ := e.IsRunning(); !r { - if err := e.WaitForStop(seconds, terminate); err != nil { - // Even timeout errors should be bubbled back up the stack. If the process didn't stop - // nicely, but the terminate argument was passed then the server is stopped without an - // error being returned. - // - // However, if terminate is not passed you'll get a context deadline error. We could - // probably handle that nicely here, but I'd rather just pass it back up the stack for now. - // Either way, any type of error indicates we should not attempt to start the server back - // up. - return err - } - } - - // Start the process. - return e.Start() -} - // Stops the container that the server is running in. This will allow up to 30 seconds to pass // before the container is forcefully terminated if we are trying to stop it without using a command // sent into the instance. diff --git a/environment/environment.go b/environment/environment.go index 4a9a4e6..ab567d0 100644 --- a/environment/environment.go +++ b/environment/environment.go @@ -47,12 +47,6 @@ type ProcessEnvironment interface { // not be returned. Stop() error - // Restart a server instance. If already stopped the process will be started. Pass the number - // of seconds to wait for the server to stop, and wether or not the process should be terminated - // if not stopped within that time period. If you pass "false" as the terminate option the server - // will not be started but the lock on the process will be released. - Restart(seconds uint, terminate bool) error - // Waits for a server instance to stop gracefully. If the server is still detected // as running after seconds, an error will be returned, or the server will be terminated // depending on the value of the second argument. diff --git a/server/power.go b/server/power.go index c463e34..3ead824 100644 --- a/server/power.go +++ b/server/power.go @@ -44,11 +44,6 @@ func (pa PowerAction) IsStart() bool { // function rather than making direct calls to the start/stop/restart functions on the // environment struct. func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error { - // Disallow start & restart if the server is suspended. - if action.IsStart() && s.IsSuspended() { - return new(suspendedError) - } - if s.powerLock == nil { s.powerLock = semaphore.NewWeighted(1) } @@ -89,33 +84,66 @@ func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error } } - // Ensure the server data is properly synced before attempting to start the process, and that there - // is enough disk space available. - if action.IsStart() { - s.Log().Info("syncing server configuration with panel") - if err := s.Sync(); err != nil { - return errors.WithStack(err) - } - - if !s.Filesystem.HasSpaceAvailable() { - return errors.New("cannot start server, not enough disk space available") - } - } - switch action { case PowerActionStart: + // Run the pre-boot logic for the server before processing the environment start. + if err := s.onBeforeStart(); err != nil { + return err + } + return s.Environment.Start() case PowerActionStop: // We're specificially waiting for the process to be stopped here, otherwise the lock is released // too soon, and you can rack up all sorts of issues. return s.Environment.WaitForStop(10 * 60, true) case PowerActionRestart: - // Same as stopping, give the process up to 10 minutes to stop before just forcibly terminating - // the process and moving on with things. - return s.Environment.Restart(10 * 60, true) + // Only try to wait for stop if the process is currently running, otherwise just skip right to the + // start event. + if r, _ := s.Environment.IsRunning(); !r { + if err := s.Environment.WaitForStop(10 * 60, true); err != nil { + // Even timeout errors should be bubbled back up the stack. If the process didn't stop + // nicely, but the terminate argument was passed then the server is stopped without an + // error being returned. + // + // However, if terminate is not passed you'll get a context deadline error. We could + // probably handle that nicely here, but I'd rather just pass it back up the stack for now. + // Either way, any type of error indicates we should not attempt to start the server back + // up. + return err + } + } + + // Now actually try to start the process by executing the normal pre-boot logic. + if err := s.onBeforeStart(); err != nil { + return err + } + + return s.Environment.Start() case PowerActionTerminate: return s.Environment.Terminate(os.Kill) } return errors.New("attempting to handle unknown power action") } + +// Execute a few functions before actually calling the environment start commands. This ensures +// that everything is ready to go for environment booting, and that the server can even be started. +func (s *Server) onBeforeStart() error { + // Disallow start & restart if the server is suspended. + if s.IsSuspended() { + return new(suspendedError) + } + + s.Log().Info("syncing server configuration with panel") + if err := s.Sync(); err != nil { + return errors.WithMessage(err, "unable to sync server data from Panel instance") + } + + if !s.Filesystem.HasSpaceAvailable() { + return errors.New("cannot start server, not enough disk space available") + } + + s.UpdateConfigurationFiles() + + return nil +} \ No newline at end of file