Add support for reinstalling a server
This commit is contained in:
parent
ddca34f9e8
commit
019d028011
17
http.go
17
http.go
|
@ -424,7 +424,7 @@ func (rt *Router) routeServerInstall(w http.ResponseWriter, r *http.Request, ps
|
||||||
s := rt.GetServer(ps.ByName("server"))
|
s := rt.GetServer(ps.ByName("server"))
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
|
|
||||||
go func (serv *server.Server) {
|
go func(serv *server.Server) {
|
||||||
if err := serv.Install(); err != nil {
|
if err := serv.Install(); err != nil {
|
||||||
zap.S().Errorw("failed to execute server installation process", zap.String("server", s.Uuid), zap.Error(err))
|
zap.S().Errorw("failed to execute server installation process", zap.String("server", s.Uuid), zap.Error(err))
|
||||||
}
|
}
|
||||||
|
@ -479,6 +479,20 @@ func (rt *Router) routeCreateServer(w http.ResponseWriter, r *http.Request, ps h
|
||||||
w.WriteHeader(http.StatusAccepted)
|
w.WriteHeader(http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rt *Router) routeServerReinstall(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
s := rt.GetServer(ps.ByName("server"))
|
||||||
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
zap.S().Infow("beginning reinstall process for server", zap.String("server", s.Uuid))
|
||||||
|
go func(server *server.Server) {
|
||||||
|
if err := server.Reinstall(); err != nil {
|
||||||
|
zap.S().Errorw("failed to complete server reinstall process", zap.String("server", server.Uuid), zap.Error(err))
|
||||||
|
}
|
||||||
|
}(s)
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusAccepted)
|
||||||
|
}
|
||||||
|
|
||||||
func (rt *Router) routeSystemInformation(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
func (rt *Router) routeSystemInformation(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
|
|
||||||
|
@ -573,6 +587,7 @@ func (rt *Router) ConfigureRouter() *httprouter.Router {
|
||||||
router.POST("/api/servers/:server/files/delete", rt.AuthenticateRequest(rt.routeServerDeleteFile))
|
router.POST("/api/servers/:server/files/delete", rt.AuthenticateRequest(rt.routeServerDeleteFile))
|
||||||
router.POST("/api/servers/:server/power", rt.AuthenticateRequest(rt.routeServerPower))
|
router.POST("/api/servers/:server/power", rt.AuthenticateRequest(rt.routeServerPower))
|
||||||
router.POST("/api/servers/:server/commands", rt.AuthenticateRequest(rt.routeServerSendCommand))
|
router.POST("/api/servers/:server/commands", rt.AuthenticateRequest(rt.routeServerSendCommand))
|
||||||
|
router.POST("/api/servers/:server/reinstall", rt.AuthenticateRequest(rt.routeServerReinstall))
|
||||||
router.PATCH("/api/servers/:server", rt.AuthenticateRequest(rt.routeServerUpdate))
|
router.PATCH("/api/servers/:server", rt.AuthenticateRequest(rt.routeServerUpdate))
|
||||||
router.DELETE("/api/servers/:server", rt.AuthenticateRequest(rt.routeServerDelete))
|
router.DELETE("/api/servers/:server", rt.AuthenticateRequest(rt.routeServerDelete))
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,11 @@ type Environment interface {
|
||||||
// not be returned.
|
// not be returned.
|
||||||
Stop() error
|
Stop() 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.
|
||||||
|
WaitForStop(seconds int, terminate bool) error
|
||||||
|
|
||||||
// Determines if the server instance exists. For example, in a docker environment
|
// Determines if the server instance exists. For example, in a docker environment
|
||||||
// this should confirm that the container is created and in a bootable state. In
|
// this should confirm that the container is created and in a bootable state. In
|
||||||
// a basic CLI environment this can probably just return true right away.
|
// a basic CLI environment this can probably just return true right away.
|
||||||
|
|
|
@ -267,6 +267,44 @@ func (d *DockerEnvironment) Stop() error {
|
||||||
return d.Client.ContainerStop(context.Background(), d.Server.Uuid, &t)
|
return d.Client.ContainerStop(context.Background(), d.Server.Uuid, &t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempts to gracefully stop a server using the defined stop command. If the server
|
||||||
|
// does not stop after seconds have passed, an error will be returned, or the instance
|
||||||
|
// will be terminated forcefully depending on the value of the second argument.
|
||||||
|
func (d *DockerEnvironment) WaitForStop(seconds int, terminate bool) error {
|
||||||
|
if d.Server.State == ProcessOfflineState {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := d.Stop(); err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// Block the return of this function until the container as been marked as no
|
||||||
|
// longer running. If this wait does not end by the time seconds have passed,
|
||||||
|
// attempt to terminate the container, or return an error.
|
||||||
|
ok, errChan := d.Client.ContainerWait(ctx, d.Server.Uuid, container.WaitConditionNotRunning)
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
if ctxErr := ctx.Err(); ctxErr != nil {
|
||||||
|
if terminate {
|
||||||
|
return d.Terminate(os.Kill)
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.WithStack(ctxErr)
|
||||||
|
}
|
||||||
|
case err := <-errChan:
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
case <-ok:
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Forcefully terminates the container using the signal passed through.
|
// Forcefully terminates the container using the signal passed through.
|
||||||
func (d *DockerEnvironment) Terminate(signal os.Signal) error {
|
func (d *DockerEnvironment) Terminate(signal os.Signal) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
|
@ -36,6 +36,19 @@ func (s *Server) Install() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.State != ProcessOfflineState {
|
||||||
|
zap.S().Debugw("waiting for server instance to enter a stopped state", zap.String("server", s.Uuid))
|
||||||
|
if err := s.Environment.WaitForStop(10, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.Install()
|
||||||
|
}
|
||||||
|
|
||||||
// Internal installation function used to simplify reporting back to the Panel.
|
// Internal installation function used to simplify reporting back to the Panel.
|
||||||
func (s *Server) internalInstall() error {
|
func (s *Server) internalInstall() error {
|
||||||
script, rerr, err := api.NewRequester().GetInstallationScript(s.Uuid)
|
script, rerr, err := api.NewRequester().GetInstallationScript(s.Uuid)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user