Add basic support for creating a server on wings
This commit is contained in:
parent
22e6ce2f7e
commit
f0da1eeb48
12
http.go
12
http.go
|
@ -399,9 +399,19 @@ func (rt *Router) routeCreateServer(w http.ResponseWriter, r *http.Request, ps h
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.S().Warnw("failed to validate the received data", zap.Error(err))
|
zap.S().Warnw("failed to validate the received data", zap.Error(err))
|
||||||
|
|
||||||
|
http.Error(w, "failed to validate data", http.StatusUnprocessableEntity)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inst.Execute()
|
// Plop that server instance onto the request so that it can be referenced in
|
||||||
|
// requests from here-on out.
|
||||||
|
rt.Servers = append(rt.Servers, inst.Server())
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// to the Panel where a reinstall may take place.
|
||||||
|
go inst.Execute()
|
||||||
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
w.WriteHeader(http.StatusAccepted)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/asaskevich/govalidator"
|
"github.com/asaskevich/govalidator"
|
||||||
"github.com/buger/jsonparser"
|
"github.com/buger/jsonparser"
|
||||||
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/server"
|
"github.com/pterodactyl/wings/server"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Installer struct {
|
type Installer struct {
|
||||||
|
@ -26,17 +29,17 @@ func New(data []byte) (error, *Installer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &server.Server{
|
s := &server.Server{
|
||||||
Uuid: getString(data, "uuid"),
|
Uuid: getString(data, "uuid"),
|
||||||
Suspended: false,
|
Suspended: false,
|
||||||
State: server.ProcessOfflineState,
|
State: server.ProcessOfflineState,
|
||||||
Invocation: "",
|
Invocation: "",
|
||||||
EnvVars: make(map[string]string),
|
EnvVars: make(map[string]string),
|
||||||
Build: &server.BuildSettings{
|
Build: &server.BuildSettings{
|
||||||
MemoryLimit: getInt(data, "build", "memory"),
|
MemoryLimit: getInt(data, "build", "memory"),
|
||||||
Swap: getInt(data, "build", "swap"),
|
Swap: getInt(data, "build", "swap"),
|
||||||
IoWeight: uint16(getInt(data, "build", "io")),
|
IoWeight: uint16(getInt(data, "build", "io")),
|
||||||
CpuLimit: getInt(data, "build", "cpu"),
|
CpuLimit: getInt(data, "build", "cpu"),
|
||||||
DiskSpace: getInt(data, "build", "disk"),
|
DiskSpace: getInt(data, "build", "disk"),
|
||||||
},
|
},
|
||||||
Allocations: &server.Allocations{
|
Allocations: &server.Allocations{
|
||||||
Mappings: make(map[string][]int),
|
Mappings: make(map[string][]int),
|
||||||
|
@ -65,8 +68,20 @@ func New(data []byte) (error, *Installer) {
|
||||||
|
|
||||||
s.Container.Image = getString(data, "container", "image")
|
s.Container.Image = getString(data, "container", "image")
|
||||||
|
|
||||||
|
b, err := WriteConfigurationToDisk(s)
|
||||||
|
if err != nil {
|
||||||
|
return err, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the temporary server instance.
|
||||||
|
s = nil
|
||||||
|
|
||||||
|
// Create a new server instance using the configuration we wrote to the disk
|
||||||
|
// so that everything gets instantiated correctly on the struct.
|
||||||
|
s2, err := server.FromConfiguration(b, config.Get().System)
|
||||||
|
|
||||||
return nil, &Installer{
|
return nil, &Installer{
|
||||||
server: s,
|
server: s2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,13 +90,44 @@ func (i *Installer) Uuid() string {
|
||||||
return i.server.Uuid
|
return i.server.Uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the server instance.
|
||||||
|
func (i *Installer) Server() *server.Server {
|
||||||
|
return i.server
|
||||||
|
}
|
||||||
|
|
||||||
// Executes the installer process, creating the server and running through the
|
// Executes the installer process, creating the server and running through the
|
||||||
// associated installation process based on the parameters passed through for
|
// associated installation process based on the parameters passed through for
|
||||||
// the server instance.
|
// the server instance.
|
||||||
func (i *Installer) Execute() error {
|
func (i *Installer) Execute() {
|
||||||
zap.S().Debugw("beginning installation process for server", zap.String("server", i.server.Uuid))
|
zap.S().Debugw("beginning installation process for server", zap.String("server", i.server.Uuid))
|
||||||
|
|
||||||
return nil
|
zap.S().Debugw("creating required environment for server instance", zap.String("server", i.server.Uuid))
|
||||||
|
if err := i.server.Environment.Create(); err != nil {
|
||||||
|
zap.S().Errorw("failed to create environment for server", zap.String("server", i.server.Uuid), zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes the server configuration to the disk and return the byte representation
|
||||||
|
// of the configuration object. This allows us to pass it directly into the
|
||||||
|
// servers.FromConfiguration() function.
|
||||||
|
func WriteConfigurationToDisk(s *server.Server) ([]byte, error) {
|
||||||
|
f, err := os.Create("data/servers/" + s.Uuid + ".yml")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
b, err := yaml.Marshal(&s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := f.Write(b); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a string value from the JSON data provided.
|
// Returns a string value from the JSON data provided.
|
||||||
|
|
|
@ -3,6 +3,7 @@ package server
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
@ -14,7 +15,6 @@ 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"
|
||||||
"golang.org/x/net/context"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -385,6 +385,8 @@ func (d *DockerEnvironment) DisableResourcePolling() error {
|
||||||
|
|
||||||
// Creates a new container for the server using all of the data that is currently
|
// 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.
|
// 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 {
|
func (d *DockerEnvironment) Create() error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
|
@ -394,6 +396,11 @@ func (d *DockerEnvironment) Create() error {
|
||||||
|
|
||||||
var oomDisabled = true
|
var oomDisabled = true
|
||||||
|
|
||||||
|
// Ensure the data directory exists before getting too far through this process.
|
||||||
|
if err := d.Server.Filesystem.EnsureDataDirectory(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// If the container already exists don't hit the user with an error, just return
|
// If the container already exists don't hit the user with an error, just return
|
||||||
// the current information about it which is what we would do when creating the
|
// the current information about it which is what we would do when creating the
|
||||||
// container anyways.
|
// container anyways.
|
||||||
|
|
|
@ -553,3 +553,18 @@ func (fs *Filesystem) ListDirectory(p string) ([]*Stat, error) {
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensures that the data directory for the server instance exists.
|
||||||
|
func (fs *Filesystem) EnsureDataDirectory() error {
|
||||||
|
if _, err := os.Stat(fs.Path()); err != nil && !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
} else if err != nil {
|
||||||
|
// Create the server data directory because it does not currently exist
|
||||||
|
// on the system.
|
||||||
|
if err := os.MkdirAll(fs.Path(), 0600); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user