Merge pull request #21 from pterodactyl/feature/server-mounts

Add configurable server mounts
This commit is contained in:
Dane Everitt 2020-07-11 17:19:51 -07:00 committed by GitHub
commit b3eba78743
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 23 deletions

View File

@ -80,6 +80,9 @@ type Configuration struct {
// The location where the panel is running that this daemon should connect to // The location where the panel is running that this daemon should connect to
// to collect data and send events. // to collect data and send events.
PanelLocation string `json:"remote" yaml:"remote"` PanelLocation string `json:"remote" yaml:"remote"`
// AllowedMounts .
AllowedMounts []string `json:"allowed_mounts" yaml:"allowed_mounts"`
} }
// Defines the configuration of the internal SFTP server. // Defines the configuration of the internal SFTP server.

View File

@ -18,6 +18,7 @@ import (
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"io" "io"
"os" "os"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -256,6 +257,7 @@ func (d *DockerEnvironment) Start() error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel() defer cancel()
if err := d.Client.ContainerStart(ctx, d.Server.Uuid, types.ContainerStartOptions{}); err != nil { if err := d.Client.ContainerStart(ctx, d.Server.Uuid, types.ContainerStartOptions{}); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -651,19 +653,57 @@ func (d *DockerEnvironment) Create() error {
}, },
} }
hostConf := &container.HostConfig{ mounts := []mount.Mount{
PortBindings: d.portBindings(),
// Configure the mounts for this container. First mount the server data directory
// into the container as a r/w bind.
Mounts: []mount.Mount{
{ {
Target: "/home/container", Target: "/home/container",
Source: d.Server.Filesystem.Path(), Source: d.Server.Filesystem.Path(),
Type: mount.TypeBind, Type: mount.TypeBind,
ReadOnly: false, ReadOnly: false,
}, },
}, }
var mounted bool
for _, m := range d.Server.Mounts {
mounted = false
source := filepath.Clean(m.Source)
target := filepath.Clean(m.Target)
for _, allowed := range config.Get().AllowedMounts {
if !strings.HasPrefix(source, allowed) {
continue
}
mounts = append(mounts, mount.Mount{
Type: mount.TypeBind,
Source: source,
Target: target,
ReadOnly: m.ReadOnly,
})
mounted = true
break
}
log := log.WithFields(log.Fields{
"server": d.Server.Uuid,
"source_path": source,
"target_path": target,
"read_only": m.ReadOnly,
})
if mounted {
log.Debug("attaching mount to server's container")
} else {
log.Warn("skipping mount because it isn't allowed")
}
}
hostConf := &container.HostConfig{
PortBindings: d.portBindings(),
// Configure the mounts for this container. First mount the server data directory
// into the container as a r/w bind.
Mounts: mounts,
// Configure the /tmp folder mapping in containers. This is necessary for some // Configure the /tmp folder mapping in containers. This is necessary for some
// games that need to make use of it for downloads and other installation processes. // games that need to make use of it for downloads and other installation processes.

8
server/mount.go Normal file
View File

@ -0,0 +1,8 @@
package server
// Mount represents a Server Mount.
type Mount struct {
Target string `json:"target"`
Source string `json:"source"`
ReadOnly bool `json:"read_only"`
}

View File

@ -74,27 +74,29 @@ type Server struct {
// An array of environment variables that should be passed along to the running // An array of environment variables that should be passed along to the running
// server process. // server process.
EnvVars EnvironmentVariables `json:"environment" yaml:"environment"` EnvVars EnvironmentVariables `json:"environment"`
Archiver Archiver `json:"-" yaml:"-"`
CrashDetection CrashDetection `json:"crash_detection" yaml:"crash_detection"`
Build BuildSettings `json:"build"`
Allocations Allocations `json:"allocations"` Allocations Allocations `json:"allocations"`
Environment Environment `json:"-" yaml:"-"` Build BuildSettings `json:"build"`
Filesystem Filesystem `json:"-" yaml:"-"` CrashDetection CrashDetection `json:"crash_detection"`
Resources ResourceUsage `json:"resources" yaml:"-"` Mounts []Mount `json:"mounts"`
Resources ResourceUsage `json:"resources"`
Archiver Archiver `json:"-"`
Environment Environment `json:"-"`
Filesystem Filesystem `json:"-"`
Container struct { Container struct {
// Defines the Docker image that will be used for this server // Defines the Docker image that will be used for this server
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`
// If set to true, OOM killer will be disabled on the server's Docker container. // If set to true, OOM killer will be disabled on the server's Docker container.
// If not present (nil) we will default to disabling it. // If not present (nil) we will default to disabling it.
OomDisabled bool `default:"true" json:"oom_disabled" yaml:"oom_disabled"` OomDisabled bool `default:"true" json:"oom_disabled"`
} `json:"container,omitempty"` } `json:"container,omitempty"`
// Server cache used to store frequently requested information in memory and make // Server cache used to store frequently requested information in memory and make
// certain long operations return faster. For example, FS disk space usage. // certain long operations return faster. For example, FS disk space usage.
Cache *cache.Cache `json:"-" yaml:"-"` Cache *cache.Cache `json:"-"`
// Events emitted by the server instance. // Events emitted by the server instance.
emitter *EventBus emitter *EventBus
@ -130,25 +132,25 @@ type InstallerDetails struct {
type BuildSettings struct { type BuildSettings struct {
// The total amount of memory in megabytes that this server is allowed to // The total amount of memory in megabytes that this server is allowed to
// use on the host system. // use on the host system.
MemoryLimit int64 `json:"memory_limit" yaml:"memory"` MemoryLimit int64 `json:"memory_limit"`
// The amount of additional swap space to be provided to a container instance. // The amount of additional swap space to be provided to a container instance.
Swap int64 `json:"swap"` Swap int64 `json:"swap"`
// The relative weight for IO operations in a container. This is relative to other // The relative weight for IO operations in a container. This is relative to other
// containers on the system and should be a value between 10 and 1000. // containers on the system and should be a value between 10 and 1000.
IoWeight uint16 `json:"io_weight" yaml:"io"` IoWeight uint16 `json:"io_weight"`
// The percentage of CPU that this instance is allowed to consume relative to // The percentage of CPU that this instance is allowed to consume relative to
// the host. A value of 200% represents complete utilization of two cores. This // the host. A value of 200% represents complete utilization of two cores. This
// should be a value between 1 and THREAD_COUNT * 100. // should be a value between 1 and THREAD_COUNT * 100.
CpuLimit int64 `json:"cpu_limit" yaml:"cpu"` CpuLimit int64 `json:"cpu_limit"`
// The amount of disk space in megabytes that a server is allowed to use. // The amount of disk space in megabytes that a server is allowed to use.
DiskSpace int64 `json:"disk_space" yaml:"disk"` DiskSpace int64 `json:"disk_space"`
// Sets which CPU threads can be used by the docker instance. // Sets which CPU threads can be used by the docker instance.
Threads string `json:"threads" yaml:"threads"` Threads string `json:"threads"`
} }
// Converts the CPU limit for a server build into a number that can be better understood // Converts the CPU limit for a server build into a number that can be better understood
@ -199,7 +201,7 @@ type Allocations struct {
DefaultMapping struct { DefaultMapping struct {
Ip string `json:"ip"` Ip string `json:"ip"`
Port int `json:"port"` Port int `json:"port"`
} `json:"default" yaml:"default"` } `json:"default"`
// Mappings contains all of the ports that should be assigned to a given server // Mappings contains all of the ports that should be assigned to a given server
// attached to the IP they correspond to. // attached to the IP they correspond to.

View File

@ -73,6 +73,10 @@ func (s *Server) UpdateDataStructure(data []byte, background bool) error {
s.Allocations.Mappings = src.Allocations.Mappings s.Allocations.Mappings = src.Allocations.Mappings
} }
if src.Mounts != nil && len(src.Mounts) > 0 {
s.Mounts = src.Mounts
}
if background { if background {
s.runBackgroundActions() s.runBackgroundActions()
} }