Rework archiving logic to be more consistent and less impactful on disk IO (#79)
Co-authored-by: Dane Everitt <dane@daneeveritt.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"emperror.dev/errors"
|
||||
"github.com/apex/log"
|
||||
"github.com/pterodactyl/wings/api"
|
||||
"github.com/pterodactyl/wings/server/backup"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
@@ -30,58 +30,38 @@ func (s *Server) notifyPanelOfBackup(uuid string, ad *backup.ArchiveDetails, suc
|
||||
}
|
||||
|
||||
// Get all of the ignored files for a server based on its .pteroignore file in the root.
|
||||
func (s *Server) getServerwideIgnoredFiles() ([]string, error) {
|
||||
var ignored []string
|
||||
|
||||
func (s *Server) getServerwideIgnoredFiles() (string, error) {
|
||||
f, err := os.Open(path.Join(s.Filesystem().Path(), ".pteroignore"))
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
// Only include non-empty lines, for the sake of clarity...
|
||||
if t := scanner.Text(); t != "" {
|
||||
ignored = append(ignored, t)
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return ignored, nil
|
||||
}
|
||||
|
||||
// Get the backup files to include when generating it.
|
||||
func (s *Server) GetIncludedBackupFiles(ignored []string) (*backup.IncludedFiles, error) {
|
||||
// If no ignored files are present in the request, check for a .pteroignore file in the root
|
||||
// of the server files directory, and use that to generate the backup.
|
||||
if len(ignored) == 0 {
|
||||
if i, err := s.getServerwideIgnoredFiles(); err != nil {
|
||||
s.Log().WithField("error", err).Warn("failed to retrieve ignored files listing for server")
|
||||
} else {
|
||||
ignored = i
|
||||
}
|
||||
b, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Get the included files based on the root path and the ignored files provided.
|
||||
return s.Filesystem().GetIncludedFiles(s.Filesystem().Path(), ignored)
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// Performs a server backup and then emits the event over the server websocket. We
|
||||
// let the actual backup system handle notifying the panel of the status, but that
|
||||
// won't emit a websocket event.
|
||||
func (s *Server) Backup(b backup.BackupInterface) error {
|
||||
// Get the included files based on the root path and the ignored files provided.
|
||||
inc, err := s.GetIncludedBackupFiles(b.Ignored())
|
||||
if err != nil {
|
||||
return err
|
||||
ignored := b.Ignored()
|
||||
if b.Ignored() == "" {
|
||||
if i, err := s.getServerwideIgnoredFiles(); err != nil {
|
||||
log.WithField("server", s.Id()).WithField("error", err).Warn("failed to get server-wide ignored files")
|
||||
} else {
|
||||
ignored = i
|
||||
}
|
||||
}
|
||||
|
||||
ad, err := b.Generate(inc, s.Filesystem().Path())
|
||||
ad, err := b.Generate(s.Filesystem().Path(), ignored)
|
||||
if err != nil {
|
||||
if notifyError := s.notifyPanelOfBackup(b.Identifier(), &backup.ArchiveDetails{}, false); notifyError != nil {
|
||||
s.Log().WithFields(log.Fields{
|
||||
@@ -109,7 +89,8 @@ func (s *Server) Backup(b backup.BackupInterface) error {
|
||||
// Try to notify the panel about the status of this backup. If for some reason this request
|
||||
// fails, delete the archive from the daemon and return that error up the chain to the caller.
|
||||
if notifyError := s.notifyPanelOfBackup(b.Identifier(), ad, true); notifyError != nil {
|
||||
b.Remove()
|
||||
_ = b.Remove()
|
||||
|
||||
s.Log().WithField("error", notifyError).Info("failed to notify panel of successful backup state")
|
||||
return err
|
||||
} else {
|
||||
@@ -118,7 +99,7 @@ func (s *Server) Backup(b backup.BackupInterface) error {
|
||||
|
||||
// Emit an event over the socket so we can update the backup in realtime on
|
||||
// the frontend for the server.
|
||||
s.Events().PublishJson(BackupCompletedEvent+":"+b.Identifier(), map[string]interface{}{
|
||||
_ = s.Events().PublishJson(BackupCompletedEvent+":"+b.Identifier(), map[string]interface{}{
|
||||
"uuid": b.Identifier(),
|
||||
"is_successful": true,
|
||||
"checksum": ad.Checksum,
|
||||
|
||||
Reference in New Issue
Block a user