Compare commits
1 Commits
v1.0.0-bet
...
v1.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ea991d86b |
2
go.mod
2
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/pterodactyl/wings
|
||||
|
||||
go 1.13
|
||||
go 1.12
|
||||
|
||||
// Uncomment this in development environments to make changes to the core SFTP
|
||||
// server software. This assumes you're using the official Pterodactyl Environment
|
||||
|
||||
1
go.sum
1
go.sum
@@ -376,7 +376,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290 h1:NXNmtp0ToD36cui5IqWy95LC4Y6vT/4y3RnPxlQPinU=
|
||||
golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b h1:zSzQJAznWxAh9fZxiPy2FZo+ZZEYoYFYYDYdOrU7AaM=
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools/gopls v0.1.3/go.mod h1:vrCQzOKxvuiZLjCKSmbbov04oeBQQOb4VQqwYK2PWIY=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/pterodactyl/wings/config"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -196,33 +197,18 @@ func (d *DockerEnvironment) Start() error {
|
||||
return &suspendedError{}
|
||||
}
|
||||
|
||||
if c, err := d.Client.ContainerInspect(context.Background(), d.Server.Uuid); err != nil {
|
||||
// Do nothing if the container is not found, we just don't want to continue
|
||||
// to the next block of code here. This check was inlined here to guard againt
|
||||
// a nil-pointer when checking c.State below.
|
||||
//
|
||||
// @see https://github.com/pterodactyl/panel/issues/2000
|
||||
if !client.IsErrNotFound(err) {
|
||||
c, err := d.Client.ContainerInspect(context.Background(), d.Server.Uuid)
|
||||
if err != nil && !client.IsErrNotFound(err) {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
} else {
|
||||
// If the server is running update our internal state and continue on with the attach.
|
||||
|
||||
// No reason to try starting a container that is already running.
|
||||
if c.State.Running {
|
||||
d.Server.SetState(ProcessRunningState)
|
||||
|
||||
return d.Attach()
|
||||
}
|
||||
|
||||
// Truncate the log file so we don't end up outputting a bunch of useless log information
|
||||
// to the websocket and whatnot. Check first that the path and file exist before trying
|
||||
// to truncate them.
|
||||
if _, err := os.Stat(c.LogPath); err == nil {
|
||||
if err := os.Truncate(c.LogPath, 0); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.Server.SetState(ProcessStartingState)
|
||||
// Set this to true for now, we will set it to false once we reach the
|
||||
// end of this chain.
|
||||
@@ -235,6 +221,15 @@ func (d *DockerEnvironment) Start() error {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
// Truncate the log file so we don't end up outputting a bunch of useless log information
|
||||
// to the websocket and whatnot. Check first that the path and file exist before trying
|
||||
// to truncate them.
|
||||
if _, err := os.Stat(c.LogPath); err == nil {
|
||||
if err := os.Truncate(c.LogPath, 0); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the configuration files defined for the server before beginning the boot process.
|
||||
// This process executes a bunch of parallel updates, so we just block until that process
|
||||
// is completed. Any errors as a result of this will just be bubbled out in the logger,
|
||||
@@ -355,19 +350,6 @@ func (d *DockerEnvironment) Destroy() error {
|
||||
func (d *DockerEnvironment) ExitState() (uint32, bool, error) {
|
||||
c, err := d.Client.ContainerInspect(context.Background(), d.Server.Uuid)
|
||||
if err != nil {
|
||||
// I'm not entirely sure how this can happen to be honest. I tried deleting a
|
||||
// container _while_ a server was running and wings gracefully saw the crash and
|
||||
// created a new container for it.
|
||||
//
|
||||
// However, someone reported an error in Discord about this scenario happening,
|
||||
// so I guess this should prevent it? They didn't tell me how they caused it though
|
||||
// so thats a mystery that will have to go unsolved.
|
||||
//
|
||||
// @see https://github.com/pterodactyl/panel/issues/2003
|
||||
if client.IsErrNotFound(err) {
|
||||
return 1, false, nil
|
||||
}
|
||||
|
||||
return 0, false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
@@ -501,7 +483,7 @@ func (d *DockerEnvironment) EnableResourcePolling() error {
|
||||
}
|
||||
|
||||
s.Resources.CpuAbsolute = s.Resources.CalculateAbsoluteCpu(&v.PreCPUStats, &v.CPUStats)
|
||||
s.Resources.Memory = s.Resources.CalculateDockerMemory(v.MemoryStats)
|
||||
s.Resources.Memory = v.MemoryStats.Usage
|
||||
s.Resources.MemoryLimit = v.MemoryStats.Limit
|
||||
|
||||
// Why you ask? This already has the logic for caching disk space in use and then
|
||||
@@ -565,6 +547,8 @@ func (d *DockerEnvironment) ensureImageExists(c *client.Client) error {
|
||||
|
||||
// Creates a new container for the server using all of the data that is currently
|
||||
// available for it. If the container already exists it will be returned.
|
||||
//
|
||||
// @todo pull the image being requested if it doesn't exist currently.
|
||||
func (d *DockerEnvironment) Create() error {
|
||||
ctx := context.Background()
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||
@@ -658,6 +642,17 @@ func (d *DockerEnvironment) Create() error {
|
||||
NetworkMode: "pterodactyl_nw",
|
||||
}
|
||||
|
||||
// Pretty sure TZ=X in the environment variables negates the need for this
|
||||
// to happen. Leaving it until I can confirm that works for everything.
|
||||
//
|
||||
// if err := mountTimezoneData(hostConf); err != nil {
|
||||
// if os.IsNotExist(err) {
|
||||
// zap.S().Warnw("the timezone data path configured does not exist on the system", zap.Error(errors.WithStack(err)))
|
||||
// } else {
|
||||
// zap.S().Warnw("failed to mount timezone data into container", zap.Error(errors.WithStack(err)))
|
||||
// }
|
||||
// }
|
||||
|
||||
if _, err := cli.ContainerCreate(ctx, conf, hostConf, nil, d.Server.Uuid); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
@@ -829,21 +824,23 @@ func (d *DockerEnvironment) exposedPorts() nat.PortSet {
|
||||
|
||||
// Formats the resources available to a server instance in such as way that Docker will
|
||||
// generate a matching environment in the container.
|
||||
//
|
||||
// This will set the actual memory limit on the container using the multiplier which is the
|
||||
// hard limit for the container (after which will result in a crash). We then set the
|
||||
// reservation to be the expected memory limit based on simply multiplication.
|
||||
//
|
||||
// The swap value is either -1 to disable it, or set to the value of the hard memory limit
|
||||
// plus the additional swap assigned to the server since Docker expects this value to be
|
||||
// the same or higher than the memory limit.
|
||||
func (d *DockerEnvironment) getResourcesForServer() container.Resources {
|
||||
overhead := 1.05
|
||||
// Set the hard limit for memory usage to be 5% more than the amount of memory assigned to
|
||||
// the server. If the memory limit for the server is < 4G, use 10%, if less than 2G use
|
||||
// 15%. This avoids unexpected crashes from processes like Java which run over the limit.
|
||||
if d.Server.Build.MemoryLimit <= 2048 {
|
||||
overhead = 1.15
|
||||
} else if d.Server.Build.MemoryLimit <= 4096 {
|
||||
overhead = 1.10;
|
||||
}
|
||||
|
||||
return container.Resources{
|
||||
Memory: d.Server.Build.BoundedMemoryLimit(),
|
||||
MemoryReservation: d.Server.Build.MemoryLimit * 1_000_000,
|
||||
Memory: int64(math.Round(float64(d.Server.Build.MemoryLimit) * 1000000.0 * overhead)),
|
||||
MemoryReservation: d.Server.Build.MemoryLimit * 1000000,
|
||||
MemorySwap: d.Server.Build.ConvertedSwap(),
|
||||
CPUQuota: d.Server.Build.ConvertedCpuLimit(),
|
||||
CPUPeriod: 100_000,
|
||||
CPUPeriod: 100000,
|
||||
CPUShares: 1024,
|
||||
BlkioWeight: d.Server.Build.IoWeight,
|
||||
OomKillDisable: &d.Server.Container.OomDisabled,
|
||||
|
||||
@@ -9,10 +9,7 @@ import (
|
||||
// should obviously expect memory and CPU usage to be 0. However, disk will always be returned
|
||||
// since that is not dependent on the server being running to collect that data.
|
||||
type ResourceUsage struct {
|
||||
// The total amount of memory, in bytes, that this server instance is consuming. This is
|
||||
// calculated slightly differently than just using the raw Memory field that the stats
|
||||
// return from the container, so please check the code setting this value for how that
|
||||
// is calculated.
|
||||
// The total amount of memory, in bytes, that this server instance is consuming.
|
||||
Memory uint64 `json:"memory_bytes"`
|
||||
// The total amount of memory this container or resource can use. Inside Docker this is
|
||||
// going to be higher than you'd expect because we're automatically allocating overhead
|
||||
@@ -31,27 +28,6 @@ type ResourceUsage struct {
|
||||
} `json:"network"`
|
||||
}
|
||||
|
||||
// The "docker stats" CLI call does not return the same value as the types.MemoryStats.Usage
|
||||
// value which can be rather confusing to people trying to compare panel usage to
|
||||
// their stats output.
|
||||
//
|
||||
// This math is straight up lifted from their CLI repository in order to show the same
|
||||
// values to avoid people bothering me about it. It should also reflect a slightly more
|
||||
// correct memory value anyways.
|
||||
//
|
||||
// @see https://github.com/docker/cli/blob/96e1d1d6/cli/command/container/stats_helpers.go#L227-L249
|
||||
func (ru *ResourceUsage) CalculateDockerMemory(stats types.MemoryStats) uint64 {
|
||||
if v, ok := stats.Stats["total_inactive_file"]; ok && v < stats.Usage {
|
||||
return stats.Usage - v
|
||||
}
|
||||
|
||||
if v := stats.Stats["inactive_file"]; v < stats.Usage {
|
||||
return stats.Usage - v
|
||||
}
|
||||
|
||||
return stats.Usage
|
||||
}
|
||||
|
||||
// Calculates the absolute CPU usage used by the server process on the system, not constrained
|
||||
// by the defined CPU limits on the container.
|
||||
//
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/pterodactyl/wings/config"
|
||||
"github.com/remeh/sizedwaitgroup"
|
||||
"go.uber.org/zap"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -113,23 +112,6 @@ func (b *BuildSettings) ConvertedCpuLimit() int64 {
|
||||
return b.CpuLimit * 1000
|
||||
}
|
||||
|
||||
// Set the hard limit for memory usage to be 5% more than the amount of memory assigned to
|
||||
// the server. If the memory limit for the server is < 4G, use 10%, if less than 2G use
|
||||
// 15%. This avoids unexpected crashes from processes like Java which run over the limit.
|
||||
func (b *BuildSettings) MemoryOverheadMultiplier() float64 {
|
||||
if b.MemoryLimit <= 2048 {
|
||||
return 1.15
|
||||
} else if b.MemoryLimit <= 4096 {
|
||||
return 1.10
|
||||
}
|
||||
|
||||
return 1.05
|
||||
}
|
||||
|
||||
func (b *BuildSettings) BoundedMemoryLimit() int64 {
|
||||
return int64(math.Round(float64(b.MemoryLimit) * b.MemoryOverheadMultiplier() * 1_000_000))
|
||||
}
|
||||
|
||||
// Returns the amount of swap available as a total in bytes. This is returned as the amount
|
||||
// of memory available to the server initially, PLUS the amount of additional swap to include
|
||||
// which is the format used by Docker.
|
||||
@@ -138,7 +120,7 @@ func (b *BuildSettings) ConvertedSwap() int64 {
|
||||
return -1
|
||||
}
|
||||
|
||||
return (b.Swap * 1_000_000) + b.BoundedMemoryLimit()
|
||||
return (b.Swap * 1000000) + (b.MemoryLimit * 1000000)
|
||||
}
|
||||
|
||||
// Defines the allocations available for a given server. When using the Docker environment
|
||||
|
||||
@@ -2,5 +2,5 @@ package system
|
||||
|
||||
const (
|
||||
// The current version of this software.
|
||||
Version = "1.0.0-beta.4"
|
||||
Version = "1.0.0-beta.3"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user