Skip to content

Commit

Permalink
simplify a bit VM's boot handling.
Browse files Browse the repository at this point in the history
Signed-off-by: António Meireles <antonio.meireles@reformi.st>
  • Loading branch information
AntonioMeireles committed Jan 14, 2016
1 parent 5f76384 commit ccf00d1
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 79 deletions.
3 changes: 0 additions & 3 deletions globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package main

import (
"sync"
"time"

"github.com/spf13/viper"
Expand Down Expand Up @@ -47,10 +46,8 @@ type (
PublicIP string
CreatedAt time.Time
publicIP chan string
wg sync.WaitGroup
errch chan error
done chan bool
exitStatus error
}
// NetworkInterface ...
NetworkInterface struct {
Expand Down
5 changes: 3 additions & 2 deletions halt.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (vm VMInfo) halt() (err error) {
}
if p, ee := os.FindProcess(vm.Pid); ee == nil {
log.Println("hard kill...")
if err = p.Kill(); err != nil {
if err = p.Signal(os.Interrupt); err != nil {
return
}
}
Expand All @@ -102,9 +102,10 @@ func (vm VMInfo) halt() (err error) {
}
// wait until it's _really_ dead, but not forever
for {
timeout := time.After(30 * time.Second)
select {
// unmounts may take a bit in slow drives...
case <-time.After(30 * time.Second):
case <-timeout:
return fmt.Errorf(fmt.Sprintf("'%s' didn't shutdown normally "+
"after 30s (!)... ", vm.Name))
case <-time.Tick(100 * time.Millisecond):
Expand Down
30 changes: 12 additions & 18 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,17 +327,12 @@ func (vm *VMInfo) isActive() bool {

func (vm *VMInfo) metadataService() (endpoint string, err error) {
var (
free net.Listener
sentCC, sentSSHk, foundGuestIP sync.Once
mux, root = http.NewServeMux(), "/" + vm.Name
rIP = func(s string) string {
return strings.Split(s, ":")[0]
}
isAllowed = func(origin string, w http.ResponseWriter) bool {
free net.Listener
foundGuestIP sync.Once
mux, root = http.NewServeMux(), "/" + vm.Name
rIP = func(s string) string { return strings.Split(s, ":")[0] }
isAllowed = func(origin string, w http.ResponseWriter) bool {
if strings.HasPrefix(origin, "192.168.64.") {
foundGuestIP.Do(func() {
vm.publicIP <- origin
})
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)
return true
Expand All @@ -352,21 +347,18 @@ func (vm *VMInfo) metadataService() (endpoint string, err error) {
return
}

vm.wg.Add(1)

if vm.CloudConfig != "" && vm.CClocation == Local {
var txt []byte
if txt, err = ioutil.ReadFile(vm.CloudConfig); err != nil {
return
}
vm.wg.Add(1)

mux.HandleFunc(root+"/cloud-config",
func(w http.ResponseWriter, r *http.Request) {
if isAllowed(rIP(r.RemoteAddr), w) {
w.Write(txt)
sentCC.Do(func() {
vm.wg.Done()
foundGuestIP.Do(func() {
vm.publicIP <- rIP(r.RemoteAddr)
})
}
})
Expand All @@ -376,9 +368,11 @@ func (vm *VMInfo) metadataService() (endpoint string, err error) {
func(w http.ResponseWriter, r *http.Request) {
if isAllowed(rIP(r.RemoteAddr), w) {
w.Write([]byte(vm.InternalSSHauthKey))
sentSSHk.Do(func() {
vm.wg.Done()
})
if !(vm.CloudConfig != "" && vm.CClocation == Local) {
foundGuestIP.Do(func() {
vm.publicIP <- rIP(r.RemoteAddr)
})
}
}
})
mux.HandleFunc(root+"/hostname",
Expand Down
86 changes: 30 additions & 56 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func vmBootstrap(args *viper.Viper) (vm *VMInfo, err error) {
vm.Cpus = args.GetInt("cpus")
vm.Extra = args.GetString("extra")
vm.SSHkey = args.GetString("sshkey")
vm.Root, vm.Pid, vm.exitStatus = -1, -1, nil
vm.Root, vm.Pid = -1, -1

vm.Name, vm.UUID = args.GetString("name"), args.GetString("uuid")

Expand Down Expand Up @@ -225,82 +225,56 @@ func (running *sessionContext) boot(slt int, rawArgs *viper.Viper) (err error) {
}

go func() {
for {
select {
case <-time.After(30 * time.Second):
if p, ee := os.FindProcess(c.Process.Pid); ee == nil {
p.Kill()
}
vm.errch <- fmt.Errorf("Unable to grab VM's pid and IP after " +
"30s (!)... Aborting")
return
case ip := <-vm.publicIP:
vm.Pid = c.Process.Pid
vm.PublicIP = ip
vm.storeConfig()
close(vm.publicIP)
timeout := time.After(30 * time.Second)
select {
case <-timeout:
if p, ee := os.FindProcess(c.Process.Pid); ee == nil {
p.Signal(os.Interrupt)
}
vm.errch <- fmt.Errorf("Unable to grab VM's IP after " +
"30s (!)... Aborting")
case ip := <-vm.publicIP:
vm.Pid, vm.PublicIP = c.Process.Pid, ip
if err = vm.storeConfig(); err != nil {
vm.errch <- err
} else {
if vm.Detached {
log.Printf("started '%s' in background with IP %v and "+
"PID %v\n", vm.Name, vm.PublicIP, c.Process.Pid)
}
return
default:
time.Sleep(100 * time.Millisecond)
}
}
}()

go func() {
defer close(vm.done)
for {
select {
case err := <-vm.errch:
if err != nil {
return
}
default:
vm.wg.Wait()
return
close(vm.publicIP)
close(vm.done)
}
}
}()

go func() {
if !vm.Detached {
c.Stdout, c.Stdin, c.Stderr = os.Stdout, os.Stdin, os.Stderr
err = c.Run()
vm.errch <- c.Run()
} else if err = c.Start(); err != nil {
vm.errch <- err
} else {
err = c.Start()
go func() {
for {
select {
case <-vm.done:
case <-vm.errch:
return
default:
if err = c.Wait(); err != nil {
log.Println(err)
vm.errch <- fmt.Errorf("VM exited with error" +
"while starting in background")
}
}
select {
default:
if err = c.Wait(); err != nil {
log.Println(err)
vm.errch <- fmt.Errorf("VM exited with error " +
"while attempting to start in background")
}
}()
case <-vm.errch:
}
}
vm.errch <- err
}()

for {
select {
case <-vm.done:
if vm.Detached {
return vm.exitStatus
}
case exit := <-vm.errch:
vm.exitStatus = exit
if exit != nil || (vm.PublicIP != "" && vm.Pid != -1) {
return vm.exitStatus
return
}
case err = <-vm.errch:
return
}
time.Sleep(250 * time.Millisecond)
}
Expand Down

0 comments on commit ccf00d1

Please sign in to comment.