internally mark if a server is restoring to restrict actions

This commit is contained in:
Matthew Penner 2021-03-12 16:19:35 -07:00
parent b63a491b5e
commit 471886dd34
5 changed files with 32 additions and 3 deletions

View File

@ -63,7 +63,7 @@ func postServerBackup(c *gin.Context) {
// This endpoint will block until the backup is fully restored allowing for a // This endpoint will block until the backup is fully restored allowing for a
// spinner to be displayed in the Panel UI effectively. // spinner to be displayed in the Panel UI effectively.
// //
// TODO: stop the server if it is running; internally mark it as suspended // TODO: stop the server if it is running
func postServerRestoreBackup(c *gin.Context) { func postServerRestoreBackup(c *gin.Context) {
s := middleware.ExtractServer(c) s := middleware.ExtractServer(c)
client := middleware.ExtractApiClient(c) client := middleware.ExtractApiClient(c)
@ -84,9 +84,19 @@ func postServerRestoreBackup(c *gin.Context) {
return return
} }
s.SetRestoring(true)
hasError := true
defer func() {
if !hasError {
return
}
s.SetRestoring(false)
}()
logger.Info("processing server backup restore request") logger.Info("processing server backup restore request")
if data.TruncateDirectory { if data.TruncateDirectory {
logger.Info(`recieved "truncate_directory" flag in request: deleting server files`) logger.Info("received \"truncate_directory\" flag in request: deleting server files")
if err := s.Filesystem().TruncateRootDirectory(); err != nil { if err := s.Filesystem().TruncateRootDirectory(); err != nil {
middleware.CaptureAndAbort(c, err) middleware.CaptureAndAbort(c, err)
return return
@ -109,7 +119,9 @@ func postServerRestoreBackup(c *gin.Context) {
s.Events().Publish(server.DaemonMessageEvent, "Completed server restoration from local backup.") s.Events().Publish(server.DaemonMessageEvent, "Completed server restoration from local backup.")
s.Events().Publish(server.BackupRestoreCompletedEvent, "") s.Events().Publish(server.BackupRestoreCompletedEvent, "")
logger.Info("completed server restoration from local backup") logger.Info("completed server restoration from local backup")
s.SetRestoring(false)
}(s, b, logger) }(s, b, logger)
hasError = false
c.Status(http.StatusAccepted) c.Status(http.StatusAccepted)
return return
} }
@ -136,7 +148,7 @@ func postServerRestoreBackup(c *gin.Context) {
} }
// Don't allow content types that we know are going to give us problems. // Don't allow content types that we know are going to give us problems.
if res.Header.Get("Content-Type") == "" || !strings.Contains("application/x-gzip application/gzip", res.Header.Get("Content-Type")) { if res.Header.Get("Content-Type") == "" || !strings.Contains("application/x-gzip application/gzip", res.Header.Get("Content-Type")) {
res.Body.Close() _ = res.Body.Close()
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "The provided backup link is not a supported content type. \"" + res.Header.Get("Content-Type") + "\" is not application/x-gzip.", "error": "The provided backup link is not a supported content type. \"" + res.Header.Get("Content-Type") + "\" is not application/x-gzip.",
}) })
@ -151,8 +163,10 @@ func postServerRestoreBackup(c *gin.Context) {
s.Events().Publish(server.DaemonMessageEvent, "Completed server restoration from S3 backup.") s.Events().Publish(server.DaemonMessageEvent, "Completed server restoration from S3 backup.")
s.Events().Publish(server.BackupRestoreCompletedEvent, "") s.Events().Publish(server.BackupRestoreCompletedEvent, "")
logger.Info("completed server restoration from S3 backup") logger.Info("completed server restoration from S3 backup")
s.SetRestoring(false)
}(s, c.Param("backup"), logger) }(s, c.Param("backup"), logger)
hasError = false
c.Status(http.StatusAccepted) c.Status(http.StatusAccepted)
} }

View File

@ -9,6 +9,7 @@ var (
ErrSuspended = errors.New("server is currently in a suspended state") ErrSuspended = errors.New("server is currently in a suspended state")
ErrServerIsInstalling = errors.New("server is currently installing") ErrServerIsInstalling = errors.New("server is currently installing")
ErrServerIsTransferring = errors.New("server is currently being transferred") ErrServerIsTransferring = errors.New("server is currently being transferred")
ErrServerIsRestoring = errors.New("server is currently being restored")
) )
type crashTooFrequent struct { type crashTooFrequent struct {

View File

@ -151,6 +151,14 @@ func (s *Server) SetTransferring(state bool) {
s.transferring.Store(state) s.transferring.Store(state)
} }
func (s *Server) IsRestoring() bool {
return s.restoring.Load()
}
func (s *Server) SetRestoring(state bool) {
s.restoring.Store(state)
}
// Removes the installer container for the server. // Removes the installer container for the server.
func (ip *InstallationProcess) RemoveContainer() error { func (ip *InstallationProcess) RemoveContainer() error {
err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", types.ContainerRemoveOptions{ err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", types.ContainerRemoveOptions{

View File

@ -70,6 +70,10 @@ func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error
return ErrServerIsTransferring return ErrServerIsTransferring
} }
if s.IsRestoring() {
return ErrServerIsRestoring
}
if s.powerLock == nil { if s.powerLock == nil {
s.powerLock = semaphore.NewWeighted(1) s.powerLock = semaphore.NewWeighted(1)
} }

View File

@ -60,6 +60,7 @@ type Server struct {
// installer process is still running. // installer process is still running.
installing *system.AtomicBool installing *system.AtomicBool
transferring *system.AtomicBool transferring *system.AtomicBool
restoring *system.AtomicBool
// The console throttler instance used to control outputs. // The console throttler instance used to control outputs.
throttler *ConsoleThrottler throttler *ConsoleThrottler
@ -79,6 +80,7 @@ func New(client remote.Client) (*Server, error) {
client: client, client: client,
installing: system.NewAtomicBool(false), installing: system.NewAtomicBool(false),
transferring: system.NewAtomicBool(false), transferring: system.NewAtomicBool(false),
restoring: system.NewAtomicBool(false),
} }
if err := defaults.Set(&s); err != nil { if err := defaults.Set(&s); err != nil {
return nil, errors.Wrap(err, "server: could not set default values for struct") return nil, errors.Wrap(err, "server: could not set default values for struct")