Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
vlssu committed Jul 7, 2024
2 parents b13bf2e + 1d8b383 commit 709f12a
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 48 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## v1.11.14

### Added

* Support relative file paths for the Wings config ([#180](https://github.com/pterodactyl/wings/pull/180))

### Fixed

* Folders not being sorted before files properly ([#5078](https://github.com/pterodactyl/panel/issues/5078)

## v1.11.13

### Fixed
Expand Down
16 changes: 8 additions & 8 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"time"

"github.com/NYTimes/logrotate"
Expand Down Expand Up @@ -379,13 +378,14 @@ func rootCmdRun(cmd *cobra.Command, _ []string) {
// Reads the configuration from the disk and then sets up the global singleton
// with all the configuration values.
func initConfig() {
if !strings.HasPrefix(configPath, "/") {
d, err := os.Getwd()
if !filepath.IsAbs(configPath) {
d, err := filepath.Abs(configPath)
if err != nil {
log2.Fatalf("cmd/root: 无法确定目录: %s", err)
log2.Fatalf("cmd/root: 无法获取配置文件的路径: %s", err)
}
configPath = path.Clean(path.Join(d, configPath))
configPath = d
}

err := config.FromFile(configPath)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
Expand Down Expand Up @@ -439,16 +439,16 @@ __ [blue][bold]Pterodactyl[reset] _____/___/_______ _______ ______
}

func exitWithConfigurationNotice() {
fmt.Print(colorstring.Color(`
fmt.Printf(colorstring.Color(`
[_red_][white][bold]错误: 找不到配置文件[reset]
Wings 找不到您的配置文件,因此无法完成其引导过程。
请确保您已将实例配置文件复制到下面的默认位置。
默认位置: /etc/pterodactyl/config.yml
默认位置: %s
[yellow]这不是该软件的错误。请不要当成软件错误进行提问,否则问题将被关闭。[reset]
`))
`), config.DefaultLocation)
os.Exit(1)
}
78 changes: 50 additions & 28 deletions environment/docker/power.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"os"
"strings"
"syscall"
"time"

"emperror.dev/errors"
Expand Down Expand Up @@ -143,42 +142,49 @@ func (e *Environment) Stop(ctx context.Context) error {
s := e.meta.Stop
e.mu.RUnlock()

// A native "stop" as the Type field value will just skip over all of this
// logic and end up only executing the container stop command (which may or
// may not work as expected).
if s.Type == "" || s.Type == remote.ProcessStopSignal {
if s.Type == "" {
log.WithField("container_id", e.Id).Warn("no stop configuration detected for environment, using termination procedure")
}
// If the process is already offline don't switch it back to stopping. Just leave it how
// it is and continue through to the stop handling for the process.
if e.st.Load() != environment.ProcessOfflineState {
e.SetState(environment.ProcessStoppingState)
}

// Handle signal based actions
if s.Type == remote.ProcessStopSignal {
log.WithField("signal_value", s.Value).Debug("stopping server using signal")

signal := os.Kill
// Handle a few common cases, otherwise just fall through and just pass along
// the os.Kill signal to the process.
// Handle some common signals - Default to SIGKILL
signal := "SIGKILL"
switch strings.ToUpper(s.Value) {
case "SIGABRT":
signal = syscall.SIGABRT
case "SIGINT":
signal = syscall.SIGINT
signal = "SIGABRT"
case "SIGINT", "C":
signal = "SIGINT"
case "SIGTERM":
signal = syscall.SIGTERM
signal = "SIGTERM"
case "SIGKILL":
signal = "SIGKILL"
default:
log.Info("Unrecognised signal requested, defaulting to SIGKILL")
}
return e.Terminate(ctx, signal)
}

// If the process is already offline don't switch it back to stopping. Just leave it how
// it is and continue through to the stop handling for the process.
if e.st.Load() != environment.ProcessOfflineState {
e.SetState(environment.ProcessStoppingState)
return e.SignalContainer(ctx, signal)

}

// Handle command based stops
// Only attempt to send the stop command to the instance if we are actually attached to
// the instance. If we are not for some reason, just send the container stop event.
if e.IsAttached() && s.Type == remote.ProcessStopCommand {
return e.SendCommand(s.Value)
}

// Allow the stop action to run for however long it takes, similar to executing a command
// and using a different logic pathway to wait for the container to stop successfully.
if s.Type == "" {
log.WithField("container_id", e.Id).Warn("no stop configuration detected for environment, using native docker stop")
}

// Fallback to a native docker stop. As we aren't passing a signal to ContainerStop docker will
// attempt to stop the container using the default stop signal, SIGTERM, unless
// another signal was specified in the Dockerfile
//
// Using a negative timeout here will allow the container to stop gracefully,
// rather than forcefully terminating it. Value is in seconds, but -1 is
Expand Down Expand Up @@ -224,7 +230,7 @@ func (e *Environment) WaitForStop(ctx context.Context, duration time.Duration, t

doTermination := func(s string) error {
e.log().WithField("step", s).WithField("duration", duration).Warn("container stop did not complete in time, terminating process...")
return e.Terminate(ctx, os.Kill)
return e.Terminate(ctx, "SIGKILL")
}

// We pass through the timed context for this stop action so that if one of the
Expand Down Expand Up @@ -268,8 +274,8 @@ func (e *Environment) WaitForStop(ctx context.Context, duration time.Duration, t
return nil
}

// Terminate forcefully terminates the container using the signal provided.
func (e *Environment) Terminate(ctx context.Context, signal os.Signal) error {
// Sends the specified signal to the container in an attempt to stop it.
func (e *Environment) SignalContainer(ctx context.Context, signal string) error {
c, err := e.ContainerInspect(ctx)
if err != nil {
// Treat missing containers as an okay error state, means it is obviously
Expand All @@ -294,11 +300,27 @@ func (e *Environment) Terminate(ctx context.Context, signal os.Signal) error {

// We set it to stopping than offline to prevent crash detection from being triggered.
e.SetState(environment.ProcessStoppingState)
sig := strings.TrimSuffix(strings.TrimPrefix(signal.String(), "signal "), "ed")
if err := e.client.ContainerKill(ctx, e.Id, sig); err != nil && !client.IsErrNotFound(err) {
if err := e.client.ContainerKill(ctx, e.Id, signal); err != nil && !client.IsErrNotFound(err) {
return errors.WithStack(err)
}

return nil

}

// Terminate forcefully terminates the container using the signal provided.
// then sets its state to stopped.
func (e *Environment) Terminate(ctx context.Context, signal string) error {

// Send the signal to the container to kill it
if err := e.SignalContainer(ctx, signal); err != nil {
return errors.WithStack(err)
}

// We expect Terminate to instantly kill the container
// so go ahead and mark it as dead and clean up
e.SetState(environment.ProcessOfflineState)

return nil

}
3 changes: 1 addition & 2 deletions environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package environment

import (
"context"
"os"
"time"

"github.com/pterodactyl/wings/events"
Expand Down Expand Up @@ -72,7 +71,7 @@ type ProcessEnvironment interface {

// Terminate stops a running server instance using the provided signal. This function
// is a no-op if the server is already stopped.
Terminate(ctx context.Context, signal os.Signal) error
Terminate(ctx context.Context, signal string) error

// Destroys the environment removing any containers that were created (in Docker
// environments at least).
Expand Down
8 changes: 4 additions & 4 deletions environment/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type Mount struct {
// Limits is the build settings for a given server that impact docker container
// creation and resource limits for a server instance.
type Limits struct {
// The total amount of memory in megabytes that this server is allowed to
// The total amount of memory in mebibytes that this server is allowed to
// use on the host system.
MemoryLimit int64 `json:"memory_limit"`

Expand Down Expand Up @@ -79,7 +79,7 @@ func (l Limits) MemoryOverheadMultiplier() float64 {
}

func (l Limits) BoundedMemoryLimit() int64 {
return int64(math.Round(float64(l.MemoryLimit) * l.MemoryOverheadMultiplier() * 1_000_000))
return int64(math.Round(float64(l.MemoryLimit) * l.MemoryOverheadMultiplier() * 1024 * 1024))
}

// ConvertedSwap returns the amount of swap available as a total in bytes. This
Expand All @@ -90,7 +90,7 @@ func (l Limits) ConvertedSwap() int64 {
return -1
}

return (l.Swap * 1_000_000) + l.BoundedMemoryLimit()
return (l.Swap * 1024 * 1024) + l.BoundedMemoryLimit()
}

// ProcessLimit returns the process limit for a container. This is currently
Expand All @@ -105,7 +105,7 @@ func (l Limits) AsContainerResources() container.Resources {
pids := l.ProcessLimit()
resources := container.Resources{
Memory: l.BoundedMemoryLimit(),
MemoryReservation: l.MemoryLimit * 1_000_000,
MemoryReservation: l.MemoryLimit * 1024 * 1024,
MemorySwap: l.ConvertedSwap(),
BlkioWeight: l.IoWeight,
OomKillDisable: &l.OOMDisabled,
Expand Down
16 changes: 14 additions & 2 deletions server/filesystem/disk_space.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package filesystem

import (
"golang.org/x/sys/unix"
"slices"
"sync"
"sync/atomic"
"time"
Expand Down Expand Up @@ -164,6 +166,8 @@ func (fs *Filesystem) DirectorySize(root string) (int64, error) {
return 0, err
}

var hardLinks []uint64

var size atomic.Int64
err = fs.unixFS.WalkDirat(dirfd, name, func(dirfd int, name, _ string, d ufs.DirEntry, err error) error {
if err != nil {
Expand All @@ -180,8 +184,16 @@ func (fs *Filesystem) DirectorySize(root string) (int64, error) {
return errors.Wrap(err, "lstatat err")
}

// TODO: detect if info is a hard-link and de-duplicate it.
// ref; https://github.com/pterodactyl/wings/pull/181/files
var sysFileInfo = info.Sys().(*unix.Stat_t)
if sysFileInfo.Nlink > 1 {
// Hard links have the same inode number
if slices.Contains(hardLinks, sysFileInfo.Ino) {
// Don't add hard links size twice
return nil
} else {
hardLinks = append(hardLinks, sysFileInfo.Ino)
}
}

size.Add(info.Size())
return nil
Expand Down
4 changes: 2 additions & 2 deletions server/filesystem/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,9 +480,9 @@ func (fs *Filesystem) ListDirectory(p string) ([]Stat, error) {
case a.IsDir() && b.IsDir():
return 0
case a.IsDir():
return 1
default:
return -1
default:
return 1
}
})

Expand Down
3 changes: 1 addition & 2 deletions server/power.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package server
import (
"context"
"fmt"
"os"
"time"

"emperror.dev/errors"
Expand Down Expand Up @@ -161,7 +160,7 @@ func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error

return s.Environment.Start(s.Context())
case PowerActionTerminate:
return s.Environment.Terminate(s.Context(), os.Kill)
return s.Environment.Terminate(s.Context(), "SIGKILL")
}

return errors.New("attempting to handle unknown power action")
Expand Down
1 change: 1 addition & 0 deletions server/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func (s *Server) SyncWithEnvironment() {
Mounts: s.Mounts(),
Allocations: cfg.Allocations,
Limits: cfg.Build,
Labels: cfg.Labels,
})

// For Docker specific environments we also want to update the configured image
Expand Down

0 comments on commit 709f12a

Please sign in to comment.