Dynamic Pools allow you to spin up or remove virtual machines running Flamenco Worker. Pools can be resized from the Flamenco Manager dashboard. The code architecture is mostly set up to support multiple platforms (like Google Compute, Amazon Web Services, Azure Batch, etc.). Currently only support for Microsoft Azure Batch has been implemented. To really properly support multiple platforms some changes will have to be made, but those are better made when there are actually multiple platforms to support. The pool status is polled periodically using the platform's API. The polling period is dynamic, and depends on whether the Manager dashboard is actually open in a browser window.
212 lines
6.7 KiB
Go
212 lines
6.7 KiB
Go
/* (c) 2019, Blender Foundation - Sybren A. Stüvel
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
* a copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"os"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/armadillica/flamenco-manager/dynamicpool/dppoller"
|
|
"github.com/armadillica/flamenco-manager/flamenco"
|
|
"github.com/armadillica/flamenco-manager/flamenco/bundledmongo"
|
|
"github.com/armadillica/flamenco-manager/httpserver"
|
|
"github.com/armadillica/flamenco-manager/jwtauth"
|
|
"github.com/armadillica/flamenco-manager/shaman"
|
|
log "github.com/sirupsen/logrus"
|
|
"gitlab.com/blender-institute/gossdp"
|
|
mgo "gopkg.in/mgo.v2"
|
|
)
|
|
|
|
var (
|
|
config flamenco.Conf
|
|
dashboard *flamenco.Dashboard
|
|
|
|
blacklist *flamenco.WorkerBlacklist
|
|
httpServer httpserver.Server
|
|
latestImageSystem *flamenco.LatestImageSystem
|
|
mongoRunner *bundledmongo.Runner
|
|
session *mgo.Session
|
|
sleeper *flamenco.SleepScheduler
|
|
ssdp *gossdp.Ssdp
|
|
taskCleaner *flamenco.TaskCleaner
|
|
taskLogUploader *flamenco.TaskLogUploader
|
|
taskScheduler *flamenco.TaskScheduler
|
|
taskUpdatePusher *flamenco.TaskUpdatePusher
|
|
taskUpdateQueue *flamenco.TaskUpdateQueue
|
|
timeoutChecker *flamenco.TimeoutChecker
|
|
upstream *flamenco.UpstreamConnection
|
|
upstreamNotifier *flamenco.UpstreamNotifier
|
|
workerRemover *flamenco.WorkerRemover
|
|
|
|
shamanServer *shaman.Server
|
|
dynamicPoolPoller *dppoller.Poller
|
|
)
|
|
|
|
var shutdownComplete chan struct{}
|
|
|
|
func shutdown(signum os.Signal) {
|
|
shutdownDone := make(chan bool)
|
|
|
|
go func() {
|
|
log.WithField("signal", signum).Info("Signal received, shutting down.")
|
|
|
|
// ImageWatcher allows long-living HTTP connections, so it
|
|
// should be shut down before the HTTP server.
|
|
if latestImageSystem != nil {
|
|
latestImageSystem.Close()
|
|
}
|
|
|
|
if ssdp != nil {
|
|
log.Info("Shutting down UPnP/SSDP advertisement")
|
|
ssdp.Stop()
|
|
}
|
|
|
|
if httpServer != nil {
|
|
log.Info("Shutting down HTTP server")
|
|
shutdownCtx, shutdownCtxCancel := context.WithTimeout(context.Background(), httpserver.ReadTimeout+1*time.Second)
|
|
defer shutdownCtxCancel()
|
|
|
|
// the Shutdown() function seems to hang sometime, even though the
|
|
// main goroutine continues execution after ListenAndServe().
|
|
go httpServer.Shutdown(shutdownCtx)
|
|
<-httpServer.Done()
|
|
} else {
|
|
log.Warning("HTTP server was not even started yet")
|
|
}
|
|
|
|
if shamanServer != nil {
|
|
shamanServer.Close()
|
|
}
|
|
jwtauth.CloseKeyStore()
|
|
|
|
if timeoutChecker != nil {
|
|
timeoutChecker.Close()
|
|
}
|
|
if taskUpdatePusher != nil {
|
|
taskUpdatePusher.Close()
|
|
}
|
|
if taskLogUploader != nil {
|
|
taskLogUploader.Close()
|
|
}
|
|
if upstream != nil {
|
|
upstream.Close()
|
|
}
|
|
if workerRemover != nil {
|
|
workerRemover.Close()
|
|
}
|
|
if mongoRunner != nil {
|
|
mongoRunner.Close(session)
|
|
}
|
|
if session != nil {
|
|
session.Close()
|
|
}
|
|
if dynamicPoolPoller != nil {
|
|
dynamicPoolPoller.Close()
|
|
}
|
|
|
|
shutdownDone <- true
|
|
}()
|
|
|
|
// Force shutdown after a bit longer than the HTTP server timeout.
|
|
select {
|
|
case <-shutdownDone:
|
|
break
|
|
case <-time.After(17 * time.Second):
|
|
log.Error("Shutdown forced, stopping process.")
|
|
os.Exit(-2)
|
|
|
|
}
|
|
|
|
log.Warning("Shutdown complete, stopping process.")
|
|
close(shutdownComplete)
|
|
}
|
|
|
|
// Commandline argument values.
|
|
// When changing, also update reconstructCliForRestart() in restart.go
|
|
var cliArgs struct {
|
|
// Influence logging:
|
|
verbose bool
|
|
quiet bool
|
|
debug bool
|
|
jsonLog bool
|
|
|
|
// Options that run a certain operation, then exit the process:
|
|
cleanSlate bool
|
|
purgeQueue bool
|
|
version bool
|
|
garbageCollect bool
|
|
iKnowWhatIAmDoing bool
|
|
|
|
// Used for setup mode and restarting the process:
|
|
setup bool // whether to start in web setup mode (true) or normal operation (false)
|
|
killPID int // PID to kill when we've started up. Used by Windows to restart Flamenco Manager.
|
|
|
|
// Run mode, see validModes in flamenco/settings.go (things like "development", "production" etc.)
|
|
// This is purely cosmetic; it is shown in the dashboard but otherwise does
|
|
// not have an impact on the behaviour of Flamenco Manager.
|
|
mode string
|
|
}
|
|
|
|
func parseCliArgs() {
|
|
flag.BoolVar(&cliArgs.verbose, "verbose", false, "Ignored as this is now the default")
|
|
flag.BoolVar(&cliArgs.quiet, "quiet", false, "Disable info-level logging")
|
|
flag.BoolVar(&cliArgs.debug, "debug", false, "Enable debug-level logging")
|
|
flag.BoolVar(&cliArgs.jsonLog, "json", false, "Log in JSON format")
|
|
flag.BoolVar(&cliArgs.cleanSlate, "cleanslate", false, "Start with a clean slate; erases all tasks from the local MongoDB")
|
|
flag.BoolVar(&cliArgs.purgeQueue, "purgequeue", false, "Purges all queued task updates from the local MongoDB")
|
|
flag.BoolVar(&cliArgs.version, "version", false, "Show the version of Flamenco Manager")
|
|
flag.BoolVar(&cliArgs.setup, "setup", false, "Enter setup mode, enabling the web-based configuration system")
|
|
|
|
flag.BoolVar(&cliArgs.garbageCollect, "gc", false, "Runs the Shaman garbage collector in dry-run mode, then exits.")
|
|
flag.BoolVar(&cliArgs.iKnowWhatIAmDoing, "i-know-what-i-am-doing", false,
|
|
"Together with -gc runs the garbage collector for real (so DELETES FILES), then exits.")
|
|
|
|
flag.StringVar(&cliArgs.mode, "mode", "", "Run mode, either 'develop' or 'production'. Overrides the 'mode' in the configuration file.")
|
|
if runtime.GOOS == "windows" {
|
|
flag.IntVar(&cliArgs.killPID, "kill-after-start", 0, "Used on Windows for restarting the daemon")
|
|
}
|
|
flag.Parse()
|
|
}
|
|
|
|
func configLogging() {
|
|
if cliArgs.jsonLog {
|
|
log.SetFormatter(&log.JSONFormatter{})
|
|
} else {
|
|
log.SetFormatter(&log.TextFormatter{
|
|
FullTimestamp: true,
|
|
})
|
|
}
|
|
|
|
// Only log the warning severity or above.
|
|
level := log.InfoLevel
|
|
if cliArgs.debug {
|
|
level = log.DebugLevel
|
|
} else if cliArgs.quiet {
|
|
level = log.WarnLevel
|
|
}
|
|
log.SetLevel(level)
|
|
}
|