2016-06-03 01:09:14 +00:00
package command
2013-12-04 07:22:26 +00:00
import (
2019-04-30 03:22:19 +00:00
"fmt"
2021-09-13 05:47:52 +00:00
"github.com/chrislusf/seaweedfs/weed/pb"
2021-03-30 08:25:28 +00:00
"github.com/chrislusf/seaweedfs/weed/util/grace"
2021-07-31 09:00:01 +00:00
"net/http"
2013-12-04 07:22:26 +00:00
"os"
"strings"
"time"
2014-10-26 18:34:55 +00:00
2020-10-29 07:24:16 +00:00
stats_collect "github.com/chrislusf/seaweedfs/weed/stats"
2016-06-03 01:09:14 +00:00
"github.com/chrislusf/seaweedfs/weed/glog"
2018-10-11 07:05:54 +00:00
"github.com/chrislusf/seaweedfs/weed/util"
2013-12-04 07:22:26 +00:00
)
2014-05-07 17:17:06 +00:00
type ServerOptions struct {
2019-06-17 21:51:47 +00:00
cpuprofile * string
2021-03-30 08:25:28 +00:00
memprofile * string
2021-07-31 09:00:01 +00:00
debug * bool
2021-07-31 16:18:41 +00:00
debugPort * int
2019-06-17 21:51:47 +00:00
v VolumeServerOptions
2014-05-07 17:17:06 +00:00
}
2014-03-31 03:57:25 +00:00
var (
2020-05-18 05:44:20 +00:00
serverOptions ServerOptions
masterOptions MasterOptions
filerOptions FilerOptions
s3Options S3Options
2022-01-14 06:49:49 +00:00
iamOptions IamOptions
2021-02-01 06:16:52 +00:00
webdavOptions WebDavOption
2020-05-18 05:44:20 +00:00
msgBrokerOptions MessageBrokerOptions
2014-03-31 03:57:25 +00:00
)
2013-12-04 07:22:26 +00:00
func init ( ) {
cmdServer . Run = runServer // break init cycle
}
var cmdServer = & Command {
2020-06-13 05:06:21 +00:00
UsageLine : "server -dir=/tmp -volume.max=5 -ip=server_name" ,
2019-04-24 07:25:20 +00:00
Short : "start a master server, a volume server, and optionally a filer and a S3 gateway" ,
2014-11-29 00:34:03 +00:00
Long : ` start both a volume server to provide storage spaces
2013-12-04 07:22:26 +00:00
and a master server to provide volume = > location mapping service and sequence number of file ids
2014-11-29 00:34:03 +00:00
2013-12-04 07:22:26 +00:00
This is provided as a convenient way to start both volume server and master server .
2019-04-24 07:25:20 +00:00
The servers acts exactly the same as starting them separately .
So other volume servers can connect to this master server also .
2014-04-26 05:09:42 +00:00
2019-04-24 07:25:20 +00:00
Optionally , a filer server can be started .
Also optionally , a S3 gateway can be started .
2019-04-24 07:18:01 +00:00
2013-12-04 07:22:26 +00:00
` ,
}
var (
2021-03-24 00:27:57 +00:00
serverIp = cmdServer . Flag . String ( "ip" , util . DetectedHostAddress ( ) , "ip or server name, also used as identifier" )
2021-03-12 23:32:51 +00:00
serverBindIp = cmdServer . Flag . String ( "ip.bind" , "" , "ip address to bind to" )
2019-06-23 22:30:16 +00:00
serverTimeout = cmdServer . Flag . Int ( "idleTimeout" , 30 , "connection idle seconds" )
serverDataCenter = cmdServer . Flag . String ( "dataCenter" , "" , "current volume server's data center name" )
serverRack = cmdServer . Flag . String ( "rack" , "" , "current volume server's rack name" )
serverWhiteListOption = cmdServer . Flag . String ( "whiteList" , "" , "comma separated Ip addresses having write permission. No limit if empty." )
serverDisableHttp = cmdServer . Flag . Bool ( "disableHttp" , false , "disable http requests, only gRPC operations are allowed." )
volumeDataFolders = cmdServer . Flag . String ( "dir" , os . TempDir ( ) , "directories to store data files. dir[,dir]..." )
2022-01-13 21:03:04 +00:00
volumeMaxDataVolumeCounts = cmdServer . Flag . String ( "volume.max" , "8" , "maximum numbers of volumes, count[,count]... If set to zero, the limit will be auto configured as free disk space divided by volume size." )
2021-04-27 02:37:24 +00:00
volumeMinFreeSpacePercent = cmdServer . Flag . String ( "volume.minFreeSpacePercent" , "1" , "minimum free disk space (default to 1%). Low disk space will mark all volumes as ReadOnly (deprecated, use minFreeSpace instead)." )
volumeMinFreeSpace = cmdServer . Flag . String ( "volume.minFreeSpace" , "" , "min free disk space (value<=100 as percentage like 1, other as human readable bytes, like 10GiB). Low disk space will mark all volumes as ReadOnly." )
2020-09-24 16:55:02 +00:00
serverMetricsHttpPort = cmdServer . Flag . Int ( "metricsPort" , 0 , "Prometheus metrics listen port" )
2020-06-05 15:18:15 +00:00
2020-06-04 17:52:01 +00:00
// pulseSeconds = cmdServer.Flag.Int("pulseSeconds", 5, "number of seconds between heartbeats")
2021-01-07 10:35:47 +00:00
isStartingMasterServer = cmdServer . Flag . Bool ( "master" , true , "whether to start master server" )
2020-10-29 07:24:16 +00:00
isStartingVolumeServer = cmdServer . Flag . Bool ( "volume" , true , "whether to start volume server" )
isStartingFiler = cmdServer . Flag . Bool ( "filer" , false , "whether to start filer" )
isStartingS3 = cmdServer . Flag . Bool ( "s3" , false , "whether to start S3 gateway" )
2022-01-14 06:49:49 +00:00
isStartingIam = cmdServer . Flag . Bool ( "iam" , false , "whether to start IAM service" )
2021-02-01 06:16:52 +00:00
isStartingWebDav = cmdServer . Flag . Bool ( "webdav" , false , "whether to start WebDAV gateway" )
2020-10-29 07:24:16 +00:00
isStartingMsgBroker = cmdServer . Flag . Bool ( "msgBroker" , false , "whether to start message broker" )
2013-12-04 07:22:26 +00:00
2016-08-05 21:45:48 +00:00
serverWhiteList [ ] string
2020-06-10 20:10:10 +00:00
False = false
2013-12-04 07:22:26 +00:00
)
2014-03-31 03:57:25 +00:00
func init ( ) {
2014-11-29 00:34:03 +00:00
serverOptions . cpuprofile = cmdServer . Flag . String ( "cpuprofile" , "" , "cpu profile output file" )
2021-03-30 08:25:28 +00:00
serverOptions . memprofile = cmdServer . Flag . String ( "memprofile" , "" , "memory profile output file" )
2021-07-31 16:18:41 +00:00
serverOptions . debug = cmdServer . Flag . Bool ( "debug" , false , "serves runtime profiling data, e.g., http://localhost:6060/debug/pprof/goroutine?debug=2" )
serverOptions . debugPort = cmdServer . Flag . Int ( "debug.port" , 6060 , "http port for debugging" )
2019-06-23 10:08:27 +00:00
masterOptions . port = cmdServer . Flag . Int ( "master.port" , 9333 , "master server http listen port" )
2021-09-20 21:05:59 +00:00
masterOptions . portGrpc = cmdServer . Flag . Int ( "master.port.grpc" , 0 , "master server grpc listen port" )
2019-06-23 10:08:27 +00:00
masterOptions . metaFolder = cmdServer . Flag . String ( "master.dir" , "" , "data directory to store meta data, default to same as -dir specified" )
masterOptions . peers = cmdServer . Flag . String ( "master.peers" , "" , "all master nodes in comma separated ip:masterPort list" )
masterOptions . volumeSizeLimitMB = cmdServer . Flag . Uint ( "master.volumeSizeLimitMB" , 30 * 1000 , "Master stops directing writes to oversized volumes." )
masterOptions . volumePreallocate = cmdServer . Flag . Bool ( "master.volumePreallocate" , false , "Preallocate disk space for volumes." )
2021-08-14 09:54:13 +00:00
masterOptions . defaultReplication = cmdServer . Flag . String ( "master.defaultReplication" , "" , "Default replication type if not specified." )
2019-06-23 10:08:27 +00:00
masterOptions . garbageThreshold = cmdServer . Flag . Float64 ( "garbageThreshold" , 0.3 , "threshold to vacuum and reclaim spaces" )
2019-06-23 22:30:16 +00:00
masterOptions . metricsAddress = cmdServer . Flag . String ( "metrics.address" , "" , "Prometheus gateway address" )
masterOptions . metricsIntervalSec = cmdServer . Flag . Int ( "metrics.intervalSeconds" , 15 , "Prometheus push interval in seconds" )
2020-10-03 20:56:38 +00:00
masterOptions . raftResumeState = cmdServer . Flag . Bool ( "resumeState" , false , "resume previous state on start master server" )
2022-02-12 10:19:49 +00:00
masterOptions . heartbeatInterval = cmdServer . Flag . Duration ( "master.heartbeatInterval" , 300 * time . Millisecond , "heartbeat interval of master servers, and will be randomly multiplied by [1, 1.25)" )
masterOptions . electionTimeout = cmdServer . Flag . Duration ( "master.electionTimeout" , 10 * time . Second , "election timeout of master servers" )
2019-06-23 10:08:27 +00:00
2014-05-13 07:03:10 +00:00
filerOptions . collection = cmdServer . Flag . String ( "filer.collection" , "" , "all data will be stored in this collection" )
filerOptions . port = cmdServer . Flag . Int ( "filer.port" , 8888 , "filer server http listen port" )
2021-09-20 21:05:59 +00:00
filerOptions . portGrpc = cmdServer . Flag . Int ( "filer.port.grpc" , 0 , "filer server grpc listen port" )
2017-05-28 03:14:22 +00:00
filerOptions . publicPort = cmdServer . Flag . Int ( "filer.port.public" , 0 , "filer server public http listen port" )
2020-09-30 16:32:00 +00:00
filerOptions . defaultReplicaPlacement = cmdServer . Flag . String ( "filer.defaultReplicaPlacement" , "" , "default replication type. If not specified, use master setting." )
2015-04-14 06:38:46 +00:00
filerOptions . disableDirListing = cmdServer . Flag . Bool ( "filer.disableDirListing" , false , "turn off directory listing" )
2021-04-01 09:21:59 +00:00
filerOptions . maxMB = cmdServer . Flag . Int ( "filer.maxMB" , 4 , "split files larger than the limit" )
2018-07-08 09:11:36 +00:00
filerOptions . dirListingLimit = cmdServer . Flag . Int ( "filer.dirListLimit" , 1000 , "limit sub dir listing size" )
2020-03-10 05:31:14 +00:00
filerOptions . cipher = cmdServer . Flag . Bool ( "filer.encryptVolumeData" , false , "encrypt data on volume servers" )
2021-01-11 07:14:46 +00:00
filerOptions . saveToFilerLimit = cmdServer . Flag . Int ( "filer.saveToFilerLimit" , 0 , "Small files smaller than this limit can be cached in filer store." )
2021-03-30 09:10:50 +00:00
filerOptions . concurrentUploadLimitMB = cmdServer . Flag . Int ( "filer.concurrentUploadLimitMB" , 64 , "limit total concurrent upload size" )
2018-10-11 07:04:31 +00:00
serverOptions . v . port = cmdServer . Flag . Int ( "volume.port" , 8080 , "volume server http listen port" )
2021-09-20 21:05:59 +00:00
serverOptions . v . portGrpc = cmdServer . Flag . Int ( "volume.port.grpc" , 0 , "volume server grpc listen port" )
2018-10-11 07:04:31 +00:00
serverOptions . v . publicPort = cmdServer . Flag . Int ( "volume.port.public" , 0 , "volume server public port" )
2019-04-09 16:42:06 +00:00
serverOptions . v . indexType = cmdServer . Flag . String ( "volume.index" , "memory" , "Choose [memory|leveldb|leveldbMedium|leveldbLarge] mode for memory~performance balance." )
2021-02-22 10:03:12 +00:00
serverOptions . v . diskType = cmdServer . Flag . String ( "volume.disk" , "" , "[hdd|ssd|<tag>] hard drive or solid state drive or any tag" )
2020-07-10 02:08:36 +00:00
serverOptions . v . fixJpgOrientation = cmdServer . Flag . Bool ( "volume.images.fix.orientation" , false , "Adjust jpg orientation when uploading." )
2021-07-03 22:55:56 +00:00
serverOptions . v . readMode = cmdServer . Flag . String ( "volume.readMode" , "proxy" , "[local|proxy|redirect] how to deal with non-local volume: 'not found|read in remote node|redirect volume location'." )
2019-05-04 00:22:39 +00:00
serverOptions . v . compactionMBPerSecond = cmdServer . Flag . Int ( "volume.compactionMBps" , 0 , "limit compaction speed in mega bytes per second" )
2020-10-29 22:46:26 +00:00
serverOptions . v . fileSizeLimitMB = cmdServer . Flag . Int ( "volume.fileSizeLimitMB" , 256 , "limit file size to avoid out of memory" )
2021-03-30 09:10:50 +00:00
serverOptions . v . concurrentUploadLimitMB = cmdServer . Flag . Int ( "volume.concurrentUploadLimitMB" , 64 , "limit total concurrent upload size" )
2021-08-09 06:25:16 +00:00
serverOptions . v . concurrentDownloadLimitMB = cmdServer . Flag . Int ( "volume.concurrentDownloadLimitMB" , 64 , "limit total concurrent download size" )
2018-10-11 07:04:31 +00:00
serverOptions . v . publicUrl = cmdServer . Flag . String ( "volume.publicUrl" , "" , "publicly accessible address" )
2020-09-12 11:05:33 +00:00
serverOptions . v . preStopSeconds = cmdServer . Flag . Int ( "volume.preStopSeconds" , 10 , "number of seconds between stop send heartbeats and stop volume server" )
2020-09-22 02:43:10 +00:00
serverOptions . v . pprof = cmdServer . Flag . Bool ( "volume.pprof" , false , "enable pprof http handlers. precludes --memprofile and --cpuprofile" )
2020-11-27 11:17:10 +00:00
serverOptions . v . idxFolder = cmdServer . Flag . String ( "volume.dir.idx" , "" , "directory to store .idx files" )
2021-03-07 22:45:36 +00:00
serverOptions . v . enableTcp = cmdServer . Flag . Bool ( "volume.tcp" , false , "<exprimental> enable tcp port" )
2018-10-11 07:04:31 +00:00
2019-04-24 07:18:01 +00:00
s3Options . port = cmdServer . Flag . Int ( "s3.port" , 8333 , "s3 server http listen port" )
2020-10-22 06:23:00 +00:00
s3Options . domainName = cmdServer . Flag . String ( "s3.domainName" , "" , "suffix of the host name in comma separated list, {bucket}.{domainName}" )
2019-04-24 07:18:01 +00:00
s3Options . tlsPrivateKey = cmdServer . Flag . String ( "s3.key.file" , "" , "path to the TLS private key file" )
s3Options . tlsCertificate = cmdServer . Flag . String ( "s3.cert.file" , "" , "path to the TLS certificate file" )
2020-02-09 22:31:51 +00:00
s3Options . config = cmdServer . Flag . String ( "s3.config" , "" , "path to the config file" )
2021-12-07 13:20:52 +00:00
s3Options . auditLogConfig = cmdServer . Flag . String ( "s3.auditLogConfig" , "" , "path to the audit log config file" )
2021-09-27 05:34:14 +00:00
s3Options . allowEmptyFolder = cmdServer . Flag . Bool ( "s3.allowEmptyFolder" , true , "allow empty folders" )
2019-04-24 07:18:01 +00:00
2022-01-14 06:49:49 +00:00
iamOptions . port = cmdServer . Flag . Int ( "iam.port" , 8111 , "iam server http listen port" )
2021-02-01 06:16:52 +00:00
webdavOptions . port = cmdServer . Flag . Int ( "webdav.port" , 7333 , "webdav server http listen port" )
webdavOptions . collection = cmdServer . Flag . String ( "webdav.collection" , "" , "collection to create the files" )
2021-02-18 20:15:09 +00:00
webdavOptions . replication = cmdServer . Flag . String ( "webdav.replication" , "" , "replication to create the files" )
2021-02-22 10:03:12 +00:00
webdavOptions . disk = cmdServer . Flag . String ( "webdav.disk" , "" , "[hdd|ssd|<tag>] hard drive or solid state drive or any tag" )
2021-02-01 06:16:52 +00:00
webdavOptions . tlsPrivateKey = cmdServer . Flag . String ( "webdav.key.file" , "" , "path to the TLS private key file" )
webdavOptions . tlsCertificate = cmdServer . Flag . String ( "webdav.cert.file" , "" , "path to the TLS certificate file" )
webdavOptions . cacheDir = cmdServer . Flag . String ( "webdav.cacheDir" , os . TempDir ( ) , "local cache directory for file chunks" )
2022-02-15 04:42:33 +00:00
webdavOptions . cacheSizeMB = cmdServer . Flag . Int64 ( "webdav.cacheCapacityMB" , 0 , "local cache capacity in MB" )
2019-04-24 07:18:01 +00:00
2020-05-18 05:44:20 +00:00
msgBrokerOptions . port = cmdServer . Flag . Int ( "msgBroker.port" , 17777 , "broker gRPC listen port" )
2014-03-31 03:57:25 +00:00
}
2013-12-04 07:22:26 +00:00
func runServer ( cmd * Command , args [ ] string ) bool {
2019-02-18 20:11:52 +00:00
2021-07-31 09:00:01 +00:00
if * serverOptions . debug {
2021-07-31 16:18:41 +00:00
go http . ListenAndServe ( fmt . Sprintf ( ":%d" , * serverOptions . debugPort ) , nil )
2021-07-31 09:00:01 +00:00
}
2019-06-05 08:30:24 +00:00
util . LoadConfiguration ( "security" , false )
util . LoadConfiguration ( "master" , false )
2019-02-18 20:11:52 +00:00
2021-03-30 08:25:28 +00:00
grace . SetupProfiling ( * serverOptions . cpuprofile , * serverOptions . memprofile )
2014-03-31 03:57:25 +00:00
2019-04-24 07:18:01 +00:00
if * isStartingS3 {
* isStartingFiler = true
}
2022-01-14 06:49:49 +00:00
if * isStartingIam {
* isStartingFiler = true
}
2021-02-01 06:16:52 +00:00
if * isStartingWebDav {
* isStartingFiler = true
}
2020-05-18 05:44:20 +00:00
if * isStartingMsgBroker {
* isStartingFiler = true
}
2019-04-24 07:18:01 +00:00
2021-10-04 09:51:26 +00:00
if * isStartingMasterServer {
_ , peerList := checkPeers ( * serverIp , * masterOptions . port , * masterOptions . portGrpc , * masterOptions . peers )
peers := strings . Join ( pb . ToAddressStrings ( peerList ) , "," )
masterOptions . peers = & peers
}
2020-09-24 16:55:02 +00:00
// ip address
2019-06-23 10:08:27 +00:00
masterOptions . ip = serverIp
masterOptions . ipBind = serverBindIp
2021-10-04 10:27:10 +00:00
filerOptions . masters = pb . ServerAddresses ( * masterOptions . peers ) . ToAddresses ( )
2020-04-21 21:21:06 +00:00
filerOptions . ip = serverIp
filerOptions . bindIp = serverBindIp
2021-12-17 19:34:37 +00:00
s3Options . bindIp = serverBindIp
2022-02-23 05:01:54 +00:00
iamOptions . masters = masterOptions . peers
2018-10-11 07:04:31 +00:00
serverOptions . v . ip = serverIp
serverOptions . v . bindIp = serverBindIp
2021-10-04 10:27:10 +00:00
serverOptions . v . masters = pb . ServerAddresses ( * masterOptions . peers ) . ToAddresses ( )
2018-10-11 07:04:31 +00:00
serverOptions . v . idleConnectionTimeout = serverTimeout
serverOptions . v . dataCenter = serverDataCenter
serverOptions . v . rack = serverRack
2020-05-18 05:44:20 +00:00
msgBrokerOptions . ip = serverIp
2019-06-23 10:11:21 +00:00
2020-06-04 17:52:01 +00:00
// serverOptions.v.pulseSeconds = pulseSeconds
// masterOptions.pulseSeconds = pulseSeconds
2014-03-31 03:57:25 +00:00
2019-06-23 10:08:27 +00:00
masterOptions . whiteList = serverWhiteListOption
2018-07-09 09:22:48 +00:00
filerOptions . dataCenter = serverDataCenter
2020-10-21 00:41:39 +00:00
filerOptions . rack = serverRack
2019-03-21 23:00:46 +00:00
filerOptions . disableHttp = serverDisableHttp
2019-06-23 10:08:27 +00:00
masterOptions . disableHttp = serverDisableHttp
2018-07-09 09:22:48 +00:00
2021-09-13 05:47:52 +00:00
filerAddress := string ( pb . NewServerAddress ( * serverIp , * filerOptions . port , * filerOptions . portGrpc ) )
2019-04-24 07:18:01 +00:00
s3Options . filer = & filerAddress
2022-01-15 11:37:52 +00:00
iamOptions . filer = & filerAddress
2021-02-01 06:16:52 +00:00
webdavOptions . filer = & filerAddress
2020-05-18 05:44:20 +00:00
msgBrokerOptions . filer = & filerAddress
2019-04-24 07:18:01 +00:00
2020-09-24 17:21:23 +00:00
go stats_collect . StartMetricsServer ( * serverMetricsHttpPort )
2013-12-04 07:22:26 +00:00
folders := strings . Split ( * volumeDataFolders , "," )
2019-06-23 10:08:27 +00:00
if * masterOptions . volumeSizeLimitMB > util . VolumeSizeLimitGB * 1000 {
2017-07-17 04:40:47 +00:00
glog . Fatalf ( "masterVolumeSizeLimitMB should be less than 30000" )
}
2019-06-23 10:08:27 +00:00
if * masterOptions . metaFolder == "" {
* masterOptions . metaFolder = folders [ 0 ]
2014-03-31 03:57:25 +00:00
}
2020-07-17 05:50:14 +00:00
if err := util . TestFolderWritable ( util . ResolvePath ( * masterOptions . metaFolder ) ) ; err != nil {
2019-06-23 10:08:27 +00:00
glog . Fatalf ( "Check Meta Folder (-mdir=\"%s\") Writable: %s" , * masterOptions . metaFolder , err )
2014-03-31 03:57:25 +00:00
}
2019-06-23 10:08:27 +00:00
filerOptions . defaultLevelDbDirectory = masterOptions . metaFolder
2014-03-31 03:57:25 +00:00
2016-08-05 21:45:48 +00:00
if * serverWhiteListOption != "" {
serverWhiteList = strings . Split ( * serverWhiteListOption , "," )
2013-12-04 07:22:26 +00:00
}
2014-03-31 03:57:25 +00:00
if * isStartingFiler {
go func ( ) {
2016-07-21 06:45:55 +00:00
time . Sleep ( 1 * time . Second )
2018-10-11 06:19:54 +00:00
filerOptions . startFiler ( )
2014-03-31 03:57:25 +00:00
} ( )
}
2014-03-30 18:28:04 +00:00
2019-04-24 07:18:01 +00:00
if * isStartingS3 {
go func ( ) {
time . Sleep ( 2 * time . Second )
s3Options . startS3Server ( )
2022-01-14 06:49:49 +00:00
} ( )
}
2019-04-24 07:18:01 +00:00
2022-01-14 06:49:49 +00:00
if * isStartingIam {
go func ( ) {
time . Sleep ( 2 * time . Second )
iamOptions . startIamServer ( )
2019-04-24 07:18:01 +00:00
} ( )
}
2021-02-01 06:16:52 +00:00
if * isStartingWebDav {
go func ( ) {
time . Sleep ( 2 * time . Second )
webdavOptions . startWebDav ( )
} ( )
}
2020-05-18 05:44:20 +00:00
if * isStartingMsgBroker {
go func ( ) {
time . Sleep ( 2 * time . Second )
msgBrokerOptions . startQueueServer ( )
} ( )
}
2019-07-28 08:55:05 +00:00
// start volume server
2020-10-29 07:24:16 +00:00
if * isStartingVolumeServer {
2021-05-28 11:19:24 +00:00
minFreeSpaces := util . MustParseMinFreeSpace ( * volumeMinFreeSpace , * volumeMinFreeSpacePercent )
2021-04-27 02:37:24 +00:00
go serverOptions . v . startVolumeServer ( * volumeDataFolders , * volumeMaxDataVolumeCounts , * serverWhiteListOption , minFreeSpaces )
2019-07-28 08:55:05 +00:00
}
2014-05-13 07:03:10 +00:00
2021-01-07 10:35:47 +00:00
if * isStartingMasterServer {
go startMaster ( masterOptions , serverWhiteList )
}
select { }
2013-12-04 07:22:26 +00:00
}