server

package
v1.0.0-rc.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2020 License: MIT Imports: 49 Imported by: 11

Documentation

Index

Constants

View Source
const (
	DaemonMessageEvent    = "daemon message"
	InstallOutputEvent    = "install output"
	InstallStartedEvent   = "install started"
	InstallCompletedEvent = "install completed"
	ConsoleOutputEvent    = "console output"
	StatusEvent           = "status"
	StatsEvent            = "stats"
	BackupCompletedEvent  = "backup completed"
)

Defines all of the possible output events for a server. noinspection GoNameStartsWithPackageName

View Source
const (
	PowerActionStart     = "start"
	PowerActionStop      = "stop"
	PowerActionRestart   = "restart"
	PowerActionTerminate = "kill"
)

The power actions that can be performed for a given server. This taps into the given server environment and performs them in a way that prevents a race condition from occurring. For example, sending two "start" actions back to back will not process the second action until the first action has been completed.

This utilizes a workerpool with a limit of one worker so that all of the actions execute in a sync manner.

Variables

This section is empty.

Functions

func IsPathResolutionError

func IsPathResolutionError(err error) bool

func IsServerDoesNotExistError

func IsServerDoesNotExistError(err error) bool

func IsSuspendedError

func IsSuspendedError(err error) bool

func IsTooFrequentCrashError

func IsTooFrequentCrashError(err error) bool

func LoadDirectory

func LoadDirectory() error

Iterates over a given directory and loads all of the servers listed before returning them to the calling function.

Types

type Archiver

type Archiver struct {
	Server *Server
}

Archiver represents a Server Archiver.

func (*Archiver) Archive

func (a *Archiver) Archive() error

Archive creates an archive of the server and deletes the previous one.

func (*Archiver) ArchiveName

func (a *Archiver) ArchiveName() string

ArchiveName returns the name of the server's archive.

func (*Archiver) ArchivePath

func (a *Archiver) ArchivePath() string

ArchivePath returns the path to the server's archive.

func (*Archiver) Checksum

func (a *Archiver) Checksum() (string, error)

Checksum computes a SHA256 checksum of the server's archive.

func (*Archiver) DeleteIfExists

func (a *Archiver) DeleteIfExists() error

DeleteIfExists deletes the archive if it exists.

func (*Archiver) Exists

func (a *Archiver) Exists() bool

Exists returns a boolean based off if the archive exists.

func (*Archiver) Stat

func (a *Archiver) Stat() (*Stat, error)

Stat stats the archive file.

type Collection

type Collection struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

func GetServers

func GetServers() *Collection

func NewCollection

func NewCollection(servers []*Server) *Collection

Create a new collection from a slice of servers.

func (*Collection) Add

func (c *Collection) Add(s *Server)

Adds an item to the collection store.

func (*Collection) All

func (c *Collection) All() []*Server

Return all of the items in the collection.

func (*Collection) Filter

func (c *Collection) Filter(filter func(*Server) bool) []*Server

Returns only those items matching the filter criteria.

func (*Collection) Find

func (c *Collection) Find(filter func(*Server) bool) *Server

Returns a single element from the collection matching the filter. If nothing is found a nil result is returned.

func (*Collection) Remove

func (c *Collection) Remove(filter func(*Server) bool)

Removes all items from the collection that match the filter function.

type Configuration

type Configuration struct {

	// The unique identifier for the server that should be used when referencing
	// it against the Panel API (and internally). This will be used when naming
	// docker containers as well as in log output.
	Uuid string `json:"uuid"`

	// Whether or not the server is in a suspended state. Suspended servers cannot
	// be started or modified except in certain scenarios by an admin user.
	Suspended bool `json:"suspended"`

	// The command that should be used when booting up the server instance.
	Invocation string `json:"invocation"`

	// By default this is false, however if selected within the Panel while installing or re-installing a
	// server, specific installation scripts will be skipped for the server process.
	SkipEggScripts bool `default:"false" json:"skip_egg_scripts"`

	// An array of environment variables that should be passed along to the running
	// server process.
	EnvVars environment.Variables `json:"environment"`

	Allocations           environment.Allocations `json:"allocations"`
	Build                 environment.Limits      `json:"build"`
	CrashDetectionEnabled bool                    `default:"true" json:"enabled" yaml:"enabled"`
	Mounts                []Mount                 `json:"mounts"`
	Resources             ResourceUsage           `json:"resources"`

	Container struct {
		// Defines the Docker image that will be used for this server
		Image string `json:"image,omitempty"`
	} `json:"container,omitempty"`
	// contains filtered or unexported fields
}

func (*Configuration) GetUuid

func (c *Configuration) GetUuid() string

func (*Configuration) SetSuspended

func (c *Configuration) SetSuspended(s bool)

type ConsoleThrottler

type ConsoleThrottler struct {
	sync.RWMutex
	config.ConsoleThrottles
	// contains filtered or unexported fields
}

func (*ConsoleThrottler) AddActivation

func (ct *ConsoleThrottler) AddActivation() uint64

Increments the number of activations for a server.

func (*ConsoleThrottler) Handle

func (ct *ConsoleThrottler) Handle()

Handles output from a server's console. This code ensures that a server is not outputting an excessive amount of data to the console that could indicate a malicious or run-away process and lead to performance issues for other users.

This was much more of a problem for the NodeJS version of the daemon which struggled to handle large volumes of output. However, this code is much more performant so I generally feel a lot better about it's abilities.

However, extreme output is still somewhat of a DoS attack vector against this software since we are still logging it to the disk temporarily and will want to avoid dumping a huge amount of data all at once. These values are all configurable via the wings configuration file, however the defaults have been in the wild for almost two years at the time of this writing, so I feel quite confident in them.

func (*ConsoleThrottler) IncrementLineCount

func (ct *ConsoleThrottler) IncrementLineCount() uint64

Increment the total count of lines that we have processed so far.

func (*ConsoleThrottler) RemoveActivation

func (ct *ConsoleThrottler) RemoveActivation() uint64

Decrements the number of activations for a server.

func (*ConsoleThrottler) ResetLineCount

func (ct *ConsoleThrottler) ResetLineCount()

Reset the line count to zero.

type CrashHandler

type CrashHandler struct {
	// contains filtered or unexported fields
}

func (*CrashHandler) LastCrashTime

func (cd *CrashHandler) LastCrashTime() time.Time

Returns the time of the last crash for this server instance.

func (*CrashHandler) SetLastCrash

func (cd *CrashHandler) SetLastCrash(t time.Time)

Sets the last crash time for a server.

type Filesystem

type Filesystem struct {
	Server *Server
	// contains filtered or unexported fields
}

func (*Filesystem) Chown

func (fs *Filesystem) Chown(path string) error

Recursively iterates over a file or directory and sets the permissions on all of the underlying files. Iterate over all of the files and directories. If it is a file just go ahead and perform the chown operation. Otherwise dig deeper into the directory until we've run out of directories to dig into.

func (*Filesystem) CompressFiles

func (fs *Filesystem) CompressFiles(dir string, paths []string) (os.FileInfo, error)

Compresses all of the files matching the given paths in the specified directory. This function also supports passing nested paths to only compress certain files and folders when working in a larger directory. This effectively creates a local backup, but rather than ignoring specific files and folders, it takes an allow-list of files and folders.

All paths are relative to the dir that is passed in as the first argument, and the compressed file will be placed at that location named `archive-{date}.tar.gz`.

func (*Filesystem) Copy

func (fs *Filesystem) Copy(p string) error

Copies a given file to the same location and appends a suffix to the file to indicate that it has been copied.

@todo need to get an exclusive lock on the file.

func (*Filesystem) CreateDirectory

func (fs *Filesystem) CreateDirectory(name string, p string) error

Creates a new directory (name) at a specified path (p) for the server.

func (*Filesystem) DecompressFile

func (fs *Filesystem) DecompressFile(dir string, file string) error

Decompress a file in a given directory by using the archiver tool to infer the file type and go from there. This will walk over all of the files within the given archive and ensure that there is not a zip-slip attack being attempted by validating that the final path is within the server data directory.

func (*Filesystem) Delete

func (fs *Filesystem) Delete(p string) error

Deletes a file or folder from the system. Prevents the user from accidentally (or maliciously) removing their root server data directory.

func (*Filesystem) DirectorySize

func (fs *Filesystem) DirectorySize(dir string) (int64, error)

Determines the directory size of a given location by running parallel tasks to iterate through all of the folders. Returns the size in bytes. This can be a fairly taxing operation on locations with tons of files, so it is recommended that you cache the output.

func (*Filesystem) DiskUsage

func (fs *Filesystem) DiskUsage(allowStaleValue bool) (int64, error)

Internal helper function to allow other parts of the codebase to check the total used disk space as needed without overly taxing the system. This will prioritize the value from the cache to avoid excessive IO usage. We will only walk the filesystem and determine the size of the directory if there is no longer a cached value.

If "allowStaleValue" is set to true, a stale value MAY be returned to the caller if there is an expired cache value AND there is currently another lookup in progress. If there is no cached value but no other lookup is in progress, a fresh disk space response will be returned to the caller.

This is primarily to avoid a bunch of I/O operations from piling up on the server, especially on servers with a large amount of files.

func (*Filesystem) EnsureDataDirectory

func (fs *Filesystem) EnsureDataDirectory() error

Ensures that the data directory for the server instance exists.

func (*Filesystem) GetIncludedFiles

func (fs *Filesystem) GetIncludedFiles(dir string, ignored []string) (*backup.IncludedFiles, error)

Given a directory, iterate through all of the files and folders within it and determine if they should be included in the output based on an array of ignored matches. This uses standard .gitignore formatting to make that determination.

If no ignored files are passed through you'll get the entire directory listing.

func (*Filesystem) HasSpaceAvailable

func (fs *Filesystem) HasSpaceAvailable(allowStaleValue bool) bool

Determines if the directory a file is trying to be added to has enough space available for the file to be written to.

Because determining the amount of space being used by a server is a taxing operation we will load it all up into a cache and pull from that as long as the key is not expired.

This operation will potentially block unless allowStaleValue is set to true. See the documentation on DiskUsage for how this affects the call.

func (*Filesystem) ListDirectory

func (fs *Filesystem) ListDirectory(p string) ([]*Stat, error)

Lists the contents of a given directory and returns stat information about each file and folder within it.

func (*Filesystem) ParallelSafePath

func (fs *Filesystem) ParallelSafePath(paths []string) ([]string, error)

Executes the fs.SafePath function in parallel against an array of paths. If any of the calls fails an error will be returned.

func (*Filesystem) Path

func (fs *Filesystem) Path() string

Returns the root path that contains all of a server's data.

func (*Filesystem) Readfile

func (fs *Filesystem) Readfile(p string) (io.Reader, error)

Reads a file on the system and returns it as a byte representation in a file reader. This is not the most memory efficient usage since it will be reading the entirety of the file into memory.

func (*Filesystem) Rename

func (fs *Filesystem) Rename(from string, to string) error

Moves (or renames) a file or directory.

func (*Filesystem) SafeJoin

func (fs *Filesystem) SafeJoin(dir string, f os.FileInfo) (string, error)

Helper function to keep some of the codebase a little cleaner. Returns a "safe" version of the path joined with a file. This is important because you cannot just assume that appending a file to a cleaned path will result in a cleaned path to that file. For example, imagine you have the following scenario:

my_bad_file -> symlink:/etc/passwd

cleaned := SafePath("../../etc") -> "/" filepath.Join(cleaned, my_bad_file) -> "/my_bad_file"

You might think that "/my_bad_file" is fine since it isn't pointing to the original "../../etc/my_bad_file". However, this doesn't account for symlinks where the file might be pointing outside of the directory, so calling a function such as Chown against it would chown the symlinked location, and not the file within the Wings daemon.

func (*Filesystem) SafePath

func (fs *Filesystem) SafePath(p string) (string, error)

Normalizes a directory being passed in to ensure the user is not able to escape from their data directory. After normalization if the directory is still within their home path it is returned. If they managed to "escape" an error will be returned.

This logic is actually copied over from the SFTP server code. Ideally that eventually either gets ported into this application, or is able to make use of this package.

func (*Filesystem) SpaceAvailableForDecompression

func (fs *Filesystem) SpaceAvailableForDecompression(dir string, file string) (bool, error)

Look through a given archive and determine if decompressing it would put the server over its allocated disk space limit.

func (*Filesystem) Stat

func (fs *Filesystem) Stat(p string) (*Stat, error)

Stats a file or folder and returns the base stat object from go along with the MIME data that can be used for editing files.

func (*Filesystem) Writefile

func (fs *Filesystem) Writefile(p string, r io.Reader) error

Writes a file to the system. If the file does not already exist one will be created.

type InstallationProcess

type InstallationProcess struct {
	Server *Server
	Script *api.InstallationScript
	// contains filtered or unexported fields
}

func NewInstallationProcess

func NewInstallationProcess(s *Server, script *api.InstallationScript) (*InstallationProcess, error)

Generates a new installation process struct that will be used to create containers, and otherwise perform installation commands for a server.

func (*InstallationProcess) AfterExecute

func (ip *InstallationProcess) AfterExecute(containerId string) error

Cleans up after the execution of the installation process. This grabs the logs from the process to store in the server configuration directory, and then destroys the associated installation container.

func (*InstallationProcess) BeforeExecute

func (ip *InstallationProcess) BeforeExecute() error

Runs before the container is executed. This pulls down the required docker container image as well as writes the installation script to the disk. This process is executed in an async manner, if either one fails the error is returned.

func (*InstallationProcess) Execute

func (ip *InstallationProcess) Execute() (string, error)

Executes the installation process inside a specially created docker container.

func (*InstallationProcess) GetLogPath

func (ip *InstallationProcess) GetLogPath() string

Returns the log path for the installation process.

func (*InstallationProcess) RemoveContainer

func (ip *InstallationProcess) RemoveContainer()

Removes the installer container for the server.

func (*InstallationProcess) Run

func (ip *InstallationProcess) Run() error

Runs the installation process, this is done as in a background thread. This will configure the required environment, and then spin up the installation container.

Once the container finishes installing the results will be stored in an installation log in the server's configuration directory.

func (*InstallationProcess) StreamOutput

func (ip *InstallationProcess) StreamOutput(id string) error

Streams the output of the installation process to a log file in the server configuration directory, as well as to a websocket listener so that the process can be viewed in the panel by administrators.

type InstallerDetails

type InstallerDetails struct {
	// contains filtered or unexported fields
}

type Mount

type Mount environment.Mount

To avoid confusion when working with mounts, assume that a server.Mount has not been properly cleaned up and had the paths set. An environment.Mount should only be returned with valid paths that have been checked.

type PathResolutionError

type PathResolutionError struct{}

Error returned when there is a bad path provided to one of the FS calls.

func (PathResolutionError) Error

func (pre PathResolutionError) Error() string

Returns the error response in a string form that can be more easily consumed.

type PowerAction

type PowerAction string

func (PowerAction) IsStart

func (pa PowerAction) IsStart() bool

func (PowerAction) IsValid

func (pa PowerAction) IsValid() bool

Checks if the power action being received is valid.

type ResourceUsage

type ResourceUsage struct {

	// Embed the current environment stats into this server specific resource usage struct.
	environment.Stats

	// The current server status.
	State string `json:"state" default:"offline"`

	// The current disk space being used by the server. This is cached to prevent slow lookup
	// issues on frequent refreshes.
	Disk int64 `json:"disk_bytes"`
	// contains filtered or unexported fields
}

Defines the current resource usage for a given server instance. If a server is offline you 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.

func (*ResourceUsage) SetDisk

func (ru *ResourceUsage) SetDisk(i int64)

type Server

type Server struct {
	// Internal mutex used to block actions that need to occur sequentially, such as
	// writing the configuration to the disk.
	sync.RWMutex

	Archiver    Archiver                       `json:"-"`
	Environment environment.ProcessEnvironment `json:"-"`
	Filesystem  Filesystem                     `json:"-"`
	// contains filtered or unexported fields
}

High level definition for a server instance being controlled by Wings.

func FromConfiguration

func FromConfiguration(data *api.ServerConfigurationResponse) (*Server, error)

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 (*Server) AbortInstallation

func (s *Server) AbortInstallation()

Aborts the server installation process by calling the cancel function on the installer context.

func (*Server) Backup

func (s *Server) Backup(b backup.BackupInterface) error

Performs a server backup and then emits the event over the server websocket. We let the actual backup system handle notifying the panel of the status, but that won't emit a websocket event.

func (*Server) Config

func (s *Server) Config() *Configuration

func (*Server) CreateEnvironment

func (s *Server) CreateEnvironment() error

Initializes a server instance. This will run through and ensure that the environment for the server is setup, and that all of the necessary files are created.

func (*Server) DiskSpace

func (s *Server) DiskSpace() int64

func (*Server) Events

func (s *Server) Events() *events.EventBus

Returns the server's emitter instance.

func (*Server) GetEnvironmentVariables

func (s *Server) GetEnvironmentVariables() []string

Returns all of the environment variables that should be assigned to a running server instance.

func (*Server) GetIncludedBackupFiles

func (s *Server) GetIncludedBackupFiles(ignored []string) (*backup.IncludedFiles, error)

Get the backup files to include when generating it.

func (*Server) GetProcessConfiguration

func (s *Server) GetProcessConfiguration() (*api.ServerConfigurationResponse, *api.RequestError, error)

Gets the process configuration data for the server.

func (*Server) GetState

func (s *Server) GetState() string

Returns the current state of the server in a race-safe manner.

func (*Server) HandlePowerAction

func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error

Helper function that can receive a power action and then process the actions that need to occur for it. This guards against someone calling Start() twice at the same time, or trying to restart while another restart process is currently running.

However, the code design for the daemon does depend on the user correctly calling this function rather than making direct calls to the start/stop/restart functions on the environment struct.

func (*Server) Id

func (s *Server) Id() string

Returns the UUID for the server instance.

func (*Server) Install

func (s *Server) Install(sync bool) error

Executes the installation stack for a server process. Bubbles any errors up to the calling function which should handle contacting the panel to notify it of the server state.

Pass true as the first argument in order to execute a server sync before the process to ensure the latest information is used.

func (*Server) IsBootable

func (s *Server) IsBootable() bool

Determine if the server is bootable in it's current state or not. This will not indicate why a server is not bootable, only if it is.

func (*Server) IsInstalling

func (s *Server) IsInstalling() bool

Determines if the server is actively running the installation process by checking the status of the semaphore lock.

func (*Server) IsRunning

func (s *Server) IsRunning() bool

Determines if the server state is running or not. This is different than the environment state, it is simply the tracked state from this daemon instance, and not the response from Docker.

func (*Server) IsSuspended

func (s *Server) IsSuspended() bool

Checks if the server is marked as being suspended or not on the system.

func (*Server) Log

func (s *Server) Log() *log.Entry

func (*Server) MemoryLimit

func (s *Server) MemoryLimit() int64

func (*Server) Mounts

func (s *Server) Mounts() []environment.Mount

Returns the default container mounts for the server instance. This includes the data directory for the server as well as any timezone related files if they exist on the host system so that servers running within the container will use the correct time.

func (*Server) Proc

func (s *Server) Proc() *ResourceUsage

Returns the resource usage stats for the server instance. If the server is not running, only the disk space currently used will be returned. When the server is running all of the other stats will be returned.

When a process is stopped all of the stats are zeroed out except for the disk.

func (*Server) ProcessConfiguration

func (s *Server) ProcessConfiguration() *api.ProcessConfiguration

func (*Server) PublishConsoleOutputFromDaemon

func (s *Server) PublishConsoleOutputFromDaemon(data string)

Sends output to the server console formatted to appear correctly as being sent from Wings.

func (*Server) ReadLogfile

func (s *Server) ReadLogfile(len int) ([]string, error)

Reads the log file for a server up to a specified number of bytes.

func (*Server) Reinstall

func (s *Server) Reinstall() error

Reinstalls a server's software by utilizing the install script for the server egg. This does not touch any existing files for the server, other than what the script modifies.

func (*Server) SetState

func (s *Server) SetState(state string) error

Sets the state of the server internally. This function handles crash detection as well as reporting to event listeners for the server.

func (*Server) StartEventListeners

func (s *Server) StartEventListeners()

Adds all of the internal event listeners we want to use for a server.

func (*Server) Sync

func (s *Server) Sync() error

Syncs the state of the server on the Panel with Wings. This ensures that we're always using the state of the server from the Panel and allows us to not require successful API calls to Wings to do things.

This also means mass actions can be performed against servers on the Panel and they will automatically sync with Wings when the server is started.

func (*Server) SyncInstallState

func (s *Server) SyncInstallState(successful bool) error

Makes a HTTP request to the Panel instance notifying it that the server has completed the installation process, and what the state of the server is. A boolean value of "true" means everything was successful, "false" means something went wrong and the server must be deleted and re-created.

func (*Server) SyncWithConfiguration

func (s *Server) SyncWithConfiguration(cfg *api.ServerConfigurationResponse) error

func (*Server) SyncWithEnvironment

func (s *Server) SyncWithEnvironment()

Updates the environment for the server to match any of the changed data. This pushes new settings and environment variables to the environment. In addition, the in-situ update method is called on the environment which will allow environments that make use of it (such as Docker) to immediately apply some settings without having to wait on a server to restart.

This functionality allows a server's resources limits to be modified on the fly and have them apply right away allowing for dynamic resource allocation and responses to abusive server processes.

func (*Server) Throttler

func (s *Server) Throttler() *ConsoleThrottler

Returns the throttler instance for the server or creates a new one.

func (*Server) UpdateConfigurationFiles

func (s *Server) UpdateConfigurationFiles()

Parent function that will update all of the defined configuration files for a server automatically to ensure that they always use the specified values.

func (*Server) UpdateDataStructure

func (s *Server) UpdateDataStructure(data []byte) error

Merges data passed through in JSON form into the existing server object. Any changes to the build settings will apply immediately in the environment if the environment supports it.

The server will be marked as requiring a rebuild on the next boot sequence, it is up to the specific environment to determine what needs to happen when that is the case.

type SpaceCheckingOpts

type SpaceCheckingOpts struct {
	AllowStaleResponse bool
}

type Stat

type Stat struct {
	Info     os.FileInfo
	Mimetype string
}

Defines the stat struct object.

func (*Stat) CTime

func (s *Stat) CTime() time.Time

Returns the time that the file/folder was created.

func (*Stat) MarshalJSON

func (s *Stat) MarshalJSON() ([]byte, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL