diff --git a/components/server/rpcservices.go b/components/server/rpcservices.go index da15c25..7346eb1 100644 --- a/components/server/rpcservices.go +++ b/components/server/rpcservices.go @@ -56,7 +56,7 @@ type ( Meta *release.Info VM *VMInfo Images map[string]semver.Versions - Running map[string]*VMInfo + Running VMmap WorkingNFS bool } ) @@ -272,6 +272,11 @@ func (s *RPCservice) Run(r *http.Request, Daemon.Jobs.Add(1) defer Daemon.Jobs.Done() Daemon.Lock() + vm.exec.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + Setsid: false, + Pgid: 0, + } err := vm.exec.Start() Daemon.Unlock() if err != nil { @@ -307,6 +312,11 @@ func (s *RPCservice) Stop(r *http.Request, } log.Info("Sky must be falling. Shutting down...") + Daemon.Lock() + Daemon.AcceptingRequests = false + Daemon.Unlock() + + Daemon.Active.array().halt() Daemon.Oops <- nil return } @@ -327,37 +337,24 @@ func (s *RPCservice) StopVMs(r *http.Request, args *RPCquery, reply *RPCreply) (err error) { log.Debug("vm:stop") - var toHalt []string + var targets VMs if !Daemon.AcceptingRequests { return ErrServerShuttingDown } if len(args.Input) == 0 { - for _, x := range Daemon.Active { - toHalt = append(toHalt, x.UUID) - } + targets = Daemon.Active.array() } else { for _, t := range args.Input { for _, v := range Daemon.Active { if v.Name == t || v.UUID == t { - toHalt = append(toHalt, v.UUID) + targets = append(targets, v) } } } } - for _, v := range toHalt { - Daemon.Active[v].halt() - for { - Daemon.Lock() - _, stillAlive := Daemon.Active[v] - Daemon.Unlock() - if !stillAlive { - break - } - time.Sleep(100 * time.Millisecond) - } - } + targets.halt() return } diff --git a/components/server/run.go b/components/server/run.go index 4053afa..c6bd66a 100644 --- a/components/server/run.go +++ b/components/server/run.go @@ -22,6 +22,7 @@ import ( "encoding/pem" "fmt" "os/exec" + "sort" "syscall" "net/http" @@ -59,6 +60,10 @@ type ( isolationCheck, callBack sync.Once cloudConfigContents []byte } + // + VMmap map[string]*VMInfo + // Config ... + VMs []*VMInfo // NetworkInterface ... NetworkInterface struct { Type int @@ -333,6 +338,25 @@ func (vm *VMInfo) assembleBootPayload() (xArgs []string, err error) { err } +func (list VMs) halt() { + sort.Sort(sort.Reverse(VMs(list))) + + for _, v := range list { + log.Info("shutting down %v...", v.Name) + Daemon.Active[v.UUID].halt() + for { + Daemon.Lock() + _, stillAlive := Daemon.Active[v.UUID] + Daemon.Unlock() + if !stillAlive { + break + } + time.Sleep(100 * time.Millisecond) + } + } + return +} + func (vm *VMInfo) halt() { // Try to gracefully terminate the process. if err := vm.exec.Process.Signal(syscall.SIGTERM); err != nil { @@ -455,3 +479,20 @@ func (volumes *StorageAssets) PrettyPrint(root int) { } } } + +func (run VMs) Len() int { + return len(run) +} +func (run VMs) Swap(i, j int) { + run[i], run[j] = run[j], run[i] +} +func (run VMs) Less(i, j int) bool { + return run[i].CreationTime.Before(run[j].CreationTime) +} + +func (in VMmap) array() (out VMs) { + for _, r := range in { + out = append(out, r) + } + return +} diff --git a/components/server/server.go b/components/server/server.go index 1eb0c7e..6733f4e 100644 --- a/components/server/server.go +++ b/components/server/server.go @@ -41,7 +41,7 @@ type ( ServerContext struct { Meta *release.Info Media MediaAssets - Active map[string]*VMInfo + Active VMmap APIserver *manners.GracefulServer EtcdServer *EtcdServer EtcdClient client.KeysAPI @@ -64,7 +64,7 @@ func New() (cfg *ServerContext) { AcceptingRequests: true, WorkingNFS: false, Oops: make(chan error, 1), - Active: make(map[string]*VMInfo), + Active: make(VMmap), } } @@ -124,6 +124,7 @@ func Start() (err error) { log.Info("Got '%v' signal, stopping server...", s) signal.Stop(hades) Daemon.Oops <- nil + Daemon.Active.array().halt() }() log.Info("server starting...") @@ -154,11 +155,6 @@ func Start() (err error) { } } - Daemon.Lock() - for _, r := range Daemon.Active { - r.halt() - } - Daemon.Unlock() Daemon.Jobs.Wait() Daemon.APIserver.Close() log.Info("gone!")