Add basic logic needed to correctly mount the VHD when initializing a server.
This commit is contained in:
parent
7fed6a68cb
commit
265f8a6b39
3
Makefile
3
Makefile
|
@ -4,6 +4,9 @@ build:
|
|||
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -gcflags "all=-trimpath=$(pwd)" -o build/wings_linux_amd64 -v wings.go
|
||||
GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -gcflags "all=-trimpath=$(pwd)" -o build/wings_linux_arm64 -v wings.go
|
||||
|
||||
race:
|
||||
go build -ldflags="-X github.com/pterodactyl/wings/system.Version=$(GIT_HEAD)" -race
|
||||
|
||||
debug:
|
||||
go build -ldflags="-X github.com/pterodactyl/wings/system.Version=$(GIT_HEAD)"
|
||||
sudo ./wings --debug --ignore-certificate-errors --config config.yml --pprof --pprof-block-rate 1
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/pterodactyl/wings/loggers/cli"
|
||||
"github.com/pterodactyl/wings/remote"
|
||||
"github.com/pterodactyl/wings/server"
|
||||
"github.com/pterodactyl/wings/server/filesystem"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -55,7 +56,7 @@ func (m *MigrateVHDCommand) Run(ctx context.Context) error {
|
|||
for _, s := range m.manager.All() {
|
||||
s.Log().Debug("starting migration of server contents to virtual disk...")
|
||||
|
||||
v := s.Filesystem().NewVHD()
|
||||
v := vhd.New(s.DiskSpace(), filesystem.VirtualDiskPath(s.Id()), s.Filesystem().Path())
|
||||
if err := v.Allocate(ctx); err != nil {
|
||||
return errors.WithStackIf(err)
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func New(ctx context.Context, manager *server.Manager, details ServerDetails) (*
|
|||
|
||||
// Create a new server instance using the configuration we wrote to the disk
|
||||
// so that everything gets instantiated correctly on the struct.
|
||||
s, err := manager.InitServer(c)
|
||||
s, err := manager.InitServer(ctx, c)
|
||||
if err != nil {
|
||||
return nil, errors.WrapIf(err, "installer: could not init server instance")
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ type CfgOption func(d *Disk) *Disk
|
|||
|
||||
// Disk represents the underlying virtual disk for the instance.
|
||||
type Disk struct {
|
||||
// The total size of the disk allowed in bytes.
|
||||
size int64
|
||||
diskPath string
|
||||
mountAt string
|
||||
|
@ -51,8 +52,8 @@ type Disk struct {
|
|||
}
|
||||
|
||||
// New returns a new Disk instance. The "size" parameter should be provided in
|
||||
// megabytes of space allowed for the disk. An additional slice of option
|
||||
// callbacks can be provided to programatically swap out the underlying filesystem
|
||||
// bytes of space allowed for the disk. An additional slice of option callbacks
|
||||
// can be provided to programatically swap out the underlying filesystem
|
||||
// implementation or the underlying command exection engine.
|
||||
func New(size int64, diskPath string, mountAt string, opts ...func(*Disk)) *Disk {
|
||||
if diskPath == "" || mountAt == "" {
|
||||
|
@ -181,7 +182,10 @@ func (d *Disk) Allocate(ctx context.Context) error {
|
|||
} else if err != nil {
|
||||
return errors.Wrap(err, "vhd: failed to check for existence of root disk")
|
||||
}
|
||||
cmd := d.commander(ctx, "fallocate", "-l", fmt.Sprintf("%dM", d.size), d.diskPath)
|
||||
// We use 1024 as the multiplier for all of the disk space logic within the
|
||||
// application. Passing "K" (/1024) is the same as "KiB" for fallocate, but
|
||||
// is different than "KB" (/1000).
|
||||
cmd := d.commander(ctx, "fallocate", "-l", fmt.Sprintf("%dK", d.size / 1024), d.diskPath)
|
||||
if _, err := cmd.Output(); err != nil {
|
||||
msg := "vhd: failed to execute fallocate command"
|
||||
if v, ok := err.(*exec.ExitError); ok {
|
||||
|
|
|
@ -62,14 +62,14 @@ func newMockDisk(c CommanderProvider) *Disk {
|
|||
if c != nil {
|
||||
w = c
|
||||
}
|
||||
return New(100, "/foo", "/bar", WithFs(afero.NewMemMapFs()), WithCommander(w))
|
||||
return New(100 * 1024 * 1024, "/foo", "/bar", WithFs(afero.NewMemMapFs()), WithCommander(w))
|
||||
}
|
||||
|
||||
func Test_New(t *testing.T) {
|
||||
t.Run("creates expected struct", func(t *testing.T) {
|
||||
d := New(100, "/foo", "/bar")
|
||||
d := New(100 * 1024 * 1024, "/foo", "/bar")
|
||||
assert.NotNil(t, d)
|
||||
assert.Equal(t, int64(100), d.size)
|
||||
assert.Equal(t, int64(100 * 1024 * 1024), d.size)
|
||||
assert.Equal(t, "/foo", d.diskPath)
|
||||
assert.Equal(t, "/bar", d.mountAt)
|
||||
|
||||
|
@ -360,7 +360,7 @@ func TestDisk_Allocate(t *testing.T) {
|
|||
output: func() ([]byte, error) {
|
||||
called = true
|
||||
assert.Equal(t, "fallocate", name)
|
||||
assert.Equal(t, []string{"-l", "100M", "/foo"}, args)
|
||||
assert.Equal(t, []string{"-l", "102400K", "/foo"}, args)
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package filesystem
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -20,6 +21,7 @@ import (
|
|||
ignore "github.com/sabhiram/go-gitignore"
|
||||
|
||||
"github.com/pterodactyl/wings/config"
|
||||
"github.com/pterodactyl/wings/internal/vhd"
|
||||
"github.com/pterodactyl/wings/system"
|
||||
)
|
||||
|
||||
|
@ -30,6 +32,7 @@ type Filesystem struct {
|
|||
diskUsed int64
|
||||
diskCheckInterval time.Duration
|
||||
denylist *ignore.GitIgnore
|
||||
vhd *vhd.Disk
|
||||
|
||||
// The maximum amount of disk space (in bytes) that this Filesystem instance can use.
|
||||
diskLimit int64
|
||||
|
@ -41,8 +44,9 @@ type Filesystem struct {
|
|||
}
|
||||
|
||||
// New creates a new Filesystem instance for a given server.
|
||||
func New(root string, size int64, denylist []string) *Filesystem {
|
||||
return &Filesystem{
|
||||
func New(uuid string, size int64, denylist []string) *Filesystem {
|
||||
root := filepath.Join(config.Get().System.Data, uuid)
|
||||
fs := Filesystem{
|
||||
root: root,
|
||||
diskLimit: size,
|
||||
diskCheckInterval: time.Duration(config.Get().System.DiskCheckInterval),
|
||||
|
@ -50,6 +54,16 @@ func New(root string, size int64, denylist []string) *Filesystem {
|
|||
lookupInProgress: system.NewAtomicBool(false),
|
||||
denylist: ignore.CompileIgnoreLines(denylist...),
|
||||
}
|
||||
|
||||
if config.Get().System.UseVirtualDisks {
|
||||
fs.vhd = vhd.New(size, VirtualDiskPath(uuid), fs.root)
|
||||
}
|
||||
|
||||
return &fs
|
||||
}
|
||||
|
||||
func VirtualDiskPath(uuid string) string {
|
||||
return filepath.Join(config.Get().System.Data, ".vhd/", uuid+".img")
|
||||
}
|
||||
|
||||
// Path returns the root path for the Filesystem instance.
|
||||
|
@ -57,6 +71,25 @@ func (fs *Filesystem) Path() string {
|
|||
return fs.root
|
||||
}
|
||||
|
||||
// IsVirtual returns true if the filesystem is currently using a virtual disk.
|
||||
func (fs *Filesystem) IsVirtual() bool {
|
||||
return fs.vhd != nil
|
||||
}
|
||||
|
||||
// MountDisk will attempt to mount the underlying virtual disk for the server.
|
||||
// If the disk is already mounted this is a no-op function. If the filesystem is
|
||||
// not configured for virtual disks this function will panic.
|
||||
func (fs *Filesystem) MountDisk(ctx context.Context) error {
|
||||
if !fs.IsVirtual() {
|
||||
panic(errors.New("filesystem: cannot call MountDisk on Filesystem instance without VHD present"))
|
||||
}
|
||||
err := fs.vhd.Mount(ctx)
|
||||
if errors.Is(err, vhd.ErrFilesystemMounted) {
|
||||
return nil
|
||||
}
|
||||
return errors.WrapIf(err, "filesystem: failed to mount VHD")
|
||||
}
|
||||
|
||||
// File returns a reader for a file instance as well as the stat information.
|
||||
func (fs *Filesystem) File(p string) (*os.File, Stat, error) {
|
||||
cleaned, err := fs.SafePath(p)
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
package filesystem
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pterodactyl/wings/config"
|
||||
"github.com/pterodactyl/wings/internal/vhd"
|
||||
)
|
||||
|
||||
func (fs *Filesystem) NewVHD() *vhd.Disk {
|
||||
parts := strings.Split(fs.root, "/")
|
||||
disk := filepath.Join(config.Get().System.Data, ".disks/", parts[len(parts)-1]+".img")
|
||||
|
||||
return vhd.New(250, disk, fs.root)
|
||||
// return vhd.New(fs.diskLimit/1024/1024, disk, fs.root)
|
||||
}
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -184,7 +183,7 @@ func (m *Manager) ReadStates() (map[string]string, error) {
|
|||
// InitServer initializes a server using a data byte array. This will be
|
||||
// marshaled into the given struct using a YAML marshaler. This will also
|
||||
// configure the given environment for a server.
|
||||
func (m *Manager) InitServer(data remote.ServerConfigurationResponse) (*Server, error) {
|
||||
func (m *Manager) InitServer(ctx context.Context, data remote.ServerConfigurationResponse) (*Server, error) {
|
||||
s, err := New(m.client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -196,7 +195,15 @@ func (m *Manager) InitServer(data remote.ServerConfigurationResponse) (*Server,
|
|||
return nil, errors.WithStackIf(err)
|
||||
}
|
||||
|
||||
s.fs = filesystem.New(filepath.Join(config.Get().System.Data, s.ID()), s.DiskSpace(), s.Config().Egg.FileDenylist)
|
||||
s.fs = filesystem.New(s.Id(), s.DiskSpace(), s.Config().Egg.FileDenylist)
|
||||
// If this is a virtuakl filesystem we need to go ahead and mount the disk
|
||||
// so that everything is accessible.
|
||||
if s.fs.IsVirtual() {
|
||||
log.WithField("server", s.Id()).Info("mounting virtual disk for server")
|
||||
if err := s.fs.MountDisk(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Right now we only support a Docker based environment, so I'm going to hard code
|
||||
// this logic in. When we're ready to support other environment we'll need to make
|
||||
|
@ -258,7 +265,7 @@ func (m *Manager) init(ctx context.Context) error {
|
|||
log.WithField("server", data.Uuid).WithField("error", err).Error("failed to parse server configuration from API response, skipping...")
|
||||
return
|
||||
}
|
||||
s, err := m.InitServer(d)
|
||||
s, err := m.InitServer(ctx, d)
|
||||
if err != nil {
|
||||
log.WithField("server", data.Uuid).WithField("error", err).Error("failed to load server, skipping...")
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue
Block a user