Add support for running installation process when creating a server
This commit is contained in:
parent
99a11f81c3
commit
7533e38543
2
data/.gitignore
vendored
2
data/.gitignore
vendored
|
@ -1 +1,3 @@
|
||||||
servers/*.yml
|
servers/*.yml
|
||||||
|
!install_logs/.gitkeep
|
||||||
|
install_logs/*
|
0
data/install_logs/.gitkeep
Normal file
0
data/install_logs/.gitkeep
Normal file
10
http.go
10
http.go
|
@ -465,11 +465,17 @@ func (rt *Router) routeCreateServer(w http.ResponseWriter, r *http.Request, ps h
|
||||||
// requests from here-on out.
|
// requests from here-on out.
|
||||||
server.GetServers().Add(inst.Server())
|
server.GetServers().Add(inst.Server())
|
||||||
|
|
||||||
|
zap.S().Infow("beginning installation process for server", zap.String("server", inst.Uuid()))
|
||||||
// Begin the installation process in the background to not block the request
|
// Begin the installation process in the background to not block the request
|
||||||
// cycle. If there are any errors they will be logged and communicated back
|
// cycle. If there are any errors they will be logged and communicated back
|
||||||
// to the Panel where a reinstall may take place.
|
// to the Panel where a reinstall may take place.
|
||||||
zap.S().Infow("beginning installation process for server", zap.String("server", inst.Uuid()))
|
go func(i *installer.Installer) {
|
||||||
go inst.Execute()
|
i.Execute()
|
||||||
|
|
||||||
|
if err := i.Server().Install(); err != nil {
|
||||||
|
zap.S().Errorw("failed to run install process for server", zap.String("server", i.Uuid()), zap.Error(err))
|
||||||
|
}
|
||||||
|
}(inst)
|
||||||
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
w.WriteHeader(http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/pterodactyl/wings/api"
|
"github.com/pterodactyl/wings/api"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -32,7 +33,15 @@ func (s *Server) Install() error {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go p.Run()
|
go func() {
|
||||||
|
zap.S().Infow("beginning installation process for server", zap.String("server", s.Uuid))
|
||||||
|
|
||||||
|
if err := p.Run(); err != nil {
|
||||||
|
zap.S().Errorw("failed to complete installation process for server", zap.String("server", s.Uuid), zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
zap.S().Infow("completed installation process for server", zap.String("server", s.Uuid))
|
||||||
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -68,27 +77,24 @@ func NewInstallationProcess(s *Server, script *api.InstallationScript) (*Install
|
||||||
//
|
//
|
||||||
// Once the container finishes installing the results will be stored in an installation
|
// Once the container finishes installing the results will be stored in an installation
|
||||||
// log in the server's configuration directory.
|
// log in the server's configuration directory.
|
||||||
func (ip *InstallationProcess) Run() {
|
func (ip *InstallationProcess) Run() error {
|
||||||
installPath, err := ip.BeforeExecute()
|
installPath, err := ip.BeforeExecute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.S().Errorw(
|
return err
|
||||||
"failed to complete BeforeExecute step of installation process",
|
|
||||||
zap.String("server", ip.Server.Uuid),
|
|
||||||
zap.Error(errors.WithStack(err)),
|
|
||||||
)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := ip.Execute(installPath); err != nil {
|
cid, err := ip.Execute(installPath)
|
||||||
zap.S().Errorw(
|
if err != nil {
|
||||||
"failed to complete Execute step of installation process",
|
return err
|
||||||
zap.String("server", ip.Server.Uuid),
|
|
||||||
zap.Error(errors.WithStack(err)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zap.S().Infow("completed installation process for server", zap.String("server", ip.Server.Uuid))
|
// If this step fails, log a warning but don't exit out of the process. This is completely
|
||||||
|
// internal to the daemon's functionality, and does not affect the status of the server itself.
|
||||||
|
if err := ip.AfterExecute(cid); err != nil {
|
||||||
|
zap.S().Warnw("failed to complete after-execute step of installation process", zap.String("server", ip.Server.Uuid), zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes the installation script to a temporary file on the host machine so that it
|
// Writes the installation script to a temporary file on the host machine so that it
|
||||||
|
@ -195,6 +201,49 @@ func (ip *InstallationProcess) BeforeExecute() (string, error) {
|
||||||
return fileName, nil
|
return fileName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
zap.S().Debugw("pulling installation logs for server", zap.String("server", ip.Server.Uuid), zap.String("container_id", containerId))
|
||||||
|
reader, err := ip.client.ContainerLogs(ctx, containerId, types.ContainerLogsOptions{
|
||||||
|
ShowStdout: true,
|
||||||
|
ShowStderr: true,
|
||||||
|
Follow: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil && !client.IsErrNotFound(err) {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.OpenFile(filepath.Join("data/install_logs/", ip.Server.Uuid+".log"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// We write the contents of the container output to a more "permanent" file so that they
|
||||||
|
// can be referenced after this container is deleted.
|
||||||
|
if _, err := io.Copy(f, reader); err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
zap.S().Debugw("removing server installation container", zap.String("server", ip.Server.Uuid), zap.String("container_id", containerId))
|
||||||
|
rErr := ip.client.ContainerRemove(ctx, containerId, types.ContainerRemoveOptions{
|
||||||
|
RemoveVolumes: true,
|
||||||
|
RemoveLinks: false,
|
||||||
|
Force: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
if rErr != nil && !client.IsErrNotFound(rErr) {
|
||||||
|
return errors.WithStack(rErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Executes the installation process inside a specially created docker container.
|
// Executes the installation process inside a specially created docker container.
|
||||||
func (ip *InstallationProcess) Execute(installPath string) (string, error) {
|
func (ip *InstallationProcess) Execute(installPath string) (string, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
@ -259,7 +308,7 @@ func (ip *InstallationProcess) Execute(installPath string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
zap.S().Infow(
|
zap.S().Infow(
|
||||||
"running installation process for server...",
|
"running installation script for server in container",
|
||||||
zap.String("server", ip.Server.Uuid),
|
zap.String("server", ip.Server.Uuid),
|
||||||
zap.String("container_id", r.ID),
|
zap.String("container_id", r.ID),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user