server(install): update installation status request
The new request includes a `reinstall` option to denote whether the installation failed for the first time, or during a reinstall. ref https://github.com/pterodactyl/panel/issues/1994
This commit is contained in:
parent
51cb6dfa42
commit
da94f750ad
|
@ -29,7 +29,7 @@ type Client interface {
|
|||
SetArchiveStatus(ctx context.Context, uuid string, successful bool) error
|
||||
SetBackupStatus(ctx context.Context, backup string, data BackupRequest) error
|
||||
SendRestorationStatus(ctx context.Context, backup string, successful bool) error
|
||||
SetInstallationStatus(ctx context.Context, uuid string, successful bool) error
|
||||
SetInstallationStatus(ctx context.Context, uuid string, data InstallStatusRequest) error
|
||||
SetTransferStatus(ctx context.Context, uuid string, successful bool) error
|
||||
ValidateSftpCredentials(ctx context.Context, request SftpAuthRequest) (SftpAuthResponse, error)
|
||||
SendActivityLogs(ctx context.Context, activity []models.Activity) error
|
||||
|
|
|
@ -19,7 +19,7 @@ const (
|
|||
ProcessStopNativeStop = "stop"
|
||||
)
|
||||
|
||||
// GetServers returns all of the servers that are present on the Panel making
|
||||
// GetServers returns all the servers that are present on the Panel making
|
||||
// parallel API calls to the endpoint if more than one page of servers is
|
||||
// returned.
|
||||
func (c *client) GetServers(ctx context.Context, limit int) ([]RawServerData, error) {
|
||||
|
@ -58,7 +58,7 @@ func (c *client) GetServers(ctx context.Context, limit int) ([]RawServerData, er
|
|||
//
|
||||
// This handles Wings exiting during either of these processes which will leave
|
||||
// things in a bad state within the Panel. This API call is executed once Wings
|
||||
// has fully booted all of the servers.
|
||||
// has fully booted all the servers.
|
||||
func (c *client) ResetServersState(ctx context.Context) error {
|
||||
res, err := c.Post(ctx, "/servers/reset", nil)
|
||||
if err != nil {
|
||||
|
@ -92,8 +92,8 @@ func (c *client) GetInstallationScript(ctx context.Context, uuid string) (Instal
|
|||
return config, err
|
||||
}
|
||||
|
||||
func (c *client) SetInstallationStatus(ctx context.Context, uuid string, successful bool) error {
|
||||
resp, err := c.Post(ctx, fmt.Sprintf("/servers/%s/install", uuid), d{"successful": successful})
|
||||
func (c *client) SetInstallationStatus(ctx context.Context, uuid string, data InstallStatusRequest) error {
|
||||
resp, err := c.Post(ctx, fmt.Sprintf("/servers/%s/install", uuid), data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ func (c *client) SetTransferStatus(ctx context.Context, uuid string, successful
|
|||
// password combination provided is associated with a valid server on the instance
|
||||
// using the Panel's authentication control mechanisms. This will get itself
|
||||
// throttled if too many requests are made, allowing us to completely offload
|
||||
// all of the authorization security logic to the Panel.
|
||||
// all the authorization security logic to the Panel.
|
||||
func (c *client) ValidateSftpCredentials(ctx context.Context, request SftpAuthRequest) (SftpAuthResponse, error) {
|
||||
var auth SftpAuthResponse
|
||||
res, err := c.Post(ctx, "/sftp/auth", request)
|
||||
|
|
|
@ -92,8 +92,8 @@ type SftpAuthResponse struct {
|
|||
}
|
||||
|
||||
type OutputLineMatcher struct {
|
||||
// The raw string to match against. This may or may not be prefixed with
|
||||
// regex: which indicates we want to match against the regex expression.
|
||||
// raw string to match against. This may or may not be prefixed with
|
||||
// `regex:` which indicates we want to match against the regex expression.
|
||||
raw []byte
|
||||
reg *regexp.Regexp
|
||||
}
|
||||
|
@ -139,9 +139,9 @@ type ProcessStopConfiguration struct {
|
|||
}
|
||||
|
||||
// ProcessConfiguration defines the process configuration for a given server
|
||||
// instance. This sets what Wings is looking for to mark a server as done starting
|
||||
// what to do when stopping, and what changes to make to the configuration file
|
||||
// for a server.
|
||||
// instance. This sets what Wings is looking for to mark a server as done
|
||||
// starting what to do when stopping, and what changes to make to the
|
||||
// configuration file for a server.
|
||||
type ProcessConfiguration struct {
|
||||
Startup struct {
|
||||
Done []*OutputLineMatcher `json:"done"`
|
||||
|
@ -169,3 +169,8 @@ type BackupRequest struct {
|
|||
Successful bool `json:"successful"`
|
||||
Parts []BackupPart `json:"parts"`
|
||||
}
|
||||
|
||||
type InstallStatusRequest struct {
|
||||
Successful bool `json:"successful"`
|
||||
Reinstall bool `json:"reinstall"`
|
||||
}
|
||||
|
|
|
@ -153,9 +153,15 @@ func postServerSync(c *gin.Context) {
|
|||
func postServerInstall(c *gin.Context) {
|
||||
s := ExtractServer(c)
|
||||
|
||||
go func(serv *server.Server) {
|
||||
if err := serv.Install(true); err != nil {
|
||||
serv.Log().WithField("error", err).Error("failed to execute server installation process")
|
||||
go func(s *server.Server) {
|
||||
s.Log().Info("syncing server state with remote source before executing installation process")
|
||||
if err := s.Sync(); err != nil {
|
||||
s.Log().WithField("error", err).Error("failed to sync server state with Panel")
|
||||
return
|
||||
}
|
||||
|
||||
if err := s.Install(); err != nil {
|
||||
s.Log().WithField("error", err).Error("failed to execute server installation process")
|
||||
}
|
||||
}(s)
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ func postCreateServer(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := i.Server().Install(false); err != nil {
|
||||
if err := i.Server().Install(); err != nil {
|
||||
log.WithFields(log.Fields{"server": i.Server().ID(), "error": err}).Error("failed to run install process for server")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -32,19 +32,17 @@ import (
|
|||
//
|
||||
// Pass true as the first argument in order to execute a server sync before the
|
||||
// process to ensure the latest information is used.
|
||||
func (s *Server) Install(sync bool) error {
|
||||
if sync {
|
||||
s.Log().Info("syncing server state with remote source before executing installation process")
|
||||
if err := s.Sync(); err != nil {
|
||||
return errors.WrapIf(err, "install: failed to sync server state with Panel")
|
||||
}
|
||||
}
|
||||
func (s *Server) Install() error {
|
||||
return s.install(false)
|
||||
}
|
||||
|
||||
func (s *Server) install(reinstall bool) error {
|
||||
var err error
|
||||
if !s.Config().SkipEggScripts {
|
||||
// Send the start event so the Panel can automatically update. We don't send this unless the process
|
||||
// is actually going to run, otherwise all sorts of weird rapid UI behavior happens since there isn't
|
||||
// an actual install process being executed.
|
||||
// Send the start event so the Panel can automatically update. We don't
|
||||
// send this unless the process is actually going to run, otherwise all
|
||||
// sorts of weird rapid UI behavior happens since there isn't an actual
|
||||
// install process being executed.
|
||||
s.Events().Publish(InstallStartedEvent, "")
|
||||
|
||||
err = s.internalInstall()
|
||||
|
@ -53,12 +51,13 @@ func (s *Server) Install(sync bool) error {
|
|||
}
|
||||
|
||||
s.Log().WithField("was_successful", err == nil).Debug("notifying panel of server install state")
|
||||
if serr := s.SyncInstallState(err == nil); serr != nil {
|
||||
if serr := s.SyncInstallState(err == nil, reinstall); serr != nil {
|
||||
l := s.Log().WithField("was_successful", err == nil)
|
||||
|
||||
// If the request was successful but there was an error with this request, attach the
|
||||
// error to this log entry. Otherwise ignore it in this log since whatever is calling
|
||||
// this function should handle the error and will end up logging the same one.
|
||||
// If the request was successful but there was an error with this request,
|
||||
// attach the error to this log entry. Otherwise, ignore it in this log
|
||||
// since whatever is calling this function should handle the error and
|
||||
// will end up logging the same one.
|
||||
if err == nil {
|
||||
l.WithField("error", err)
|
||||
}
|
||||
|
@ -66,19 +65,20 @@ func (s *Server) Install(sync bool) error {
|
|||
l.Warn("failed to notify panel of server install state")
|
||||
}
|
||||
|
||||
// Ensure that the server is marked as offline at this point, otherwise you end up
|
||||
// with a blank value which is a bit confusing.
|
||||
// Ensure that the server is marked as offline at this point, otherwise you
|
||||
// end up with a blank value which is a bit confusing.
|
||||
s.Environment.SetState(environment.ProcessOfflineState)
|
||||
|
||||
// Push an event to the websocket so we can auto-refresh the information in the panel once
|
||||
// the install is completed.
|
||||
// Push an event to the websocket, so we can auto-refresh the information in
|
||||
// the panel once the installation is completed.
|
||||
s.Events().Publish(InstallCompletedEvent, "")
|
||||
|
||||
return errors.WithStackIf(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.
|
||||
// Reinstall reinstalls a server's software by utilizing the installation 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.Environment.State() != environment.ProcessOfflineState {
|
||||
s.Log().Debug("waiting for server instance to enter a stopped state")
|
||||
|
@ -87,7 +87,12 @@ func (s *Server) Reinstall() error {
|
|||
}
|
||||
}
|
||||
|
||||
return s.Install(true)
|
||||
s.Log().Info("syncing server state with remote source before executing re-installation process")
|
||||
if err := s.Sync(); err != nil {
|
||||
return errors.WrapIf(err, "install: failed to sync server state with Panel")
|
||||
}
|
||||
|
||||
return s.install(true)
|
||||
}
|
||||
|
||||
// Internal installation function used to simplify reporting back to the Panel.
|
||||
|
@ -116,8 +121,9 @@ type InstallationProcess struct {
|
|||
client *client.Client
|
||||
}
|
||||
|
||||
// Generates a new installation process struct that will be used to create containers,
|
||||
// and otherwise perform installation commands for a server.
|
||||
// NewInstallationProcess returns a new installation process struct that will be
|
||||
// used to create containers and otherwise perform installation commands for a
|
||||
// server.
|
||||
func NewInstallationProcess(s *Server, script *remote.InstallationScript) (*InstallationProcess, error) {
|
||||
proc := &InstallationProcess{
|
||||
Script: script,
|
||||
|
@ -133,8 +139,8 @@ func NewInstallationProcess(s *Server, script *remote.InstallationScript) (*Inst
|
|||
return proc, nil
|
||||
}
|
||||
|
||||
// Determines if the server is actively running the installation process by checking the status
|
||||
// of the installer lock.
|
||||
// IsInstalling returns if the server is actively running the installation
|
||||
// process by checking the status of the installer lock.
|
||||
func (s *Server) IsInstalling() bool {
|
||||
return s.installing.Load()
|
||||
}
|
||||
|
@ -155,7 +161,7 @@ func (s *Server) SetRestoring(state bool) {
|
|||
s.restoring.Store(state)
|
||||
}
|
||||
|
||||
// Removes the installer container for the server.
|
||||
// RemoveContainer removes the installation container for the server.
|
||||
func (ip *InstallationProcess) RemoveContainer() error {
|
||||
err := ip.client.ContainerRemove(ip.Server.Context(), ip.Server.ID()+"_installer", types.ContainerRemoveOptions{
|
||||
RemoveVolumes: true,
|
||||
|
@ -328,14 +334,14 @@ func (ip *InstallationProcess) BeforeExecute() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Returns the log path for the installation process.
|
||||
// GetLogPath returns the log path for the installation process.
|
||||
func (ip *InstallationProcess) GetLogPath() string {
|
||||
return filepath.Join(config.Get().System.LogDirectory, "/install", ip.Server.ID()+".log")
|
||||
}
|
||||
|
||||
// Cleans up after the execution of the installation process. This grabs the logs from the
|
||||
// process to store in the server configuration directory, and then destroys the associated
|
||||
// installation container.
|
||||
// AfterExecute cleans up after the execution of the installation process.
|
||||
// This grabs the logs from the process to store in the server configuration
|
||||
// directory, and then destroys the associated installation container.
|
||||
func (ip *InstallationProcess) AfterExecute(containerId string) error {
|
||||
defer ip.RemoveContainer()
|
||||
|
||||
|
@ -525,7 +531,7 @@ func (ip *InstallationProcess) StreamOutput(ctx context.Context, id string) erro
|
|||
return nil
|
||||
}
|
||||
|
||||
// resourceLimits returns the install container specific resource limits. This
|
||||
// resourceLimits returns resource limits for the installation container. This
|
||||
// looks at the globally defined install container limits and attempts to use
|
||||
// the higher of the two (defined limits & server limits). This allows for servers
|
||||
// with super low limits (e.g. Discord bots with 128Mb of memory) to perform more
|
||||
|
@ -537,8 +543,8 @@ func (ip *InstallationProcess) StreamOutput(ctx context.Context, id string) erro
|
|||
func (ip *InstallationProcess) resourceLimits() container.Resources {
|
||||
limits := config.Get().Docker.InstallerLimits
|
||||
|
||||
// Create a copy of the configuration so we're not accidentally making changes
|
||||
// to the underlying server build data.
|
||||
// Create a copy of the configuration, so we're not accidentally making
|
||||
// changes to the underlying server build data.
|
||||
c := *ip.Server.Config()
|
||||
cfg := c.Build
|
||||
if cfg.MemoryLimit < limits.Memory {
|
||||
|
@ -562,10 +568,12 @@ func (ip *InstallationProcess) resourceLimits() container.Resources {
|
|||
return resources
|
||||
}
|
||||
|
||||
// SyncInstallState makes a HTTP request to the Panel instance notifying it that
|
||||
// SyncInstallState makes an HTTP request to the Panel instance notifying it that
|
||||
// the server has completed the installation process, and what the state of the
|
||||
// server is. A boolean value of "true" means everything was successful, "false"
|
||||
// means something went wrong and the server must be deleted and re-created.
|
||||
func (s *Server) SyncInstallState(successful bool) error {
|
||||
return s.client.SetInstallationStatus(s.Context(), s.ID(), successful)
|
||||
// server is.
|
||||
func (s *Server) SyncInstallState(successful, reinstall bool) error {
|
||||
return s.client.SetInstallationStatus(s.Context(), s.ID(), remote.InstallStatusRequest{
|
||||
Successful: successful,
|
||||
Reinstall: reinstall,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user