github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/client/driver/lxc_test.go (about) 1 //+build linux,lxc 2 3 package driver 4 5 import ( 6 "fmt" 7 "os" 8 "path/filepath" 9 "testing" 10 "time" 11 12 "github.com/hashicorp/nomad/client/config" 13 "github.com/hashicorp/nomad/nomad/structs" 14 "github.com/hashicorp/nomad/testutil" 15 lxc "gopkg.in/lxc/go-lxc.v2" 16 ) 17 18 func TestLxcDriver_Fingerprint(t *testing.T) { 19 t.Parallel() 20 if !lxcPresent(t) { 21 t.Skip("lxc not present") 22 } 23 24 task := &structs.Task{ 25 Name: "foo", 26 Driver: "lxc", 27 Resources: structs.DefaultResources(), 28 } 29 30 ctx := testDriverContexts(t, task) 31 defer ctx.AllocDir.Destroy() 32 d := NewLxcDriver(ctx.DriverCtx) 33 34 node := &structs.Node{ 35 Attributes: map[string]string{}, 36 } 37 apply, err := d.Fingerprint(&config.Config{}, node) 38 if err != nil { 39 t.Fatalf("err: %v", err) 40 } 41 if !apply { 42 t.Fatalf("should apply by default") 43 } 44 45 apply, err = d.Fingerprint(&config.Config{Options: map[string]string{lxcConfigOption: "0"}}, node) 46 if err != nil { 47 t.Fatalf("err: %v", err) 48 } 49 if apply { 50 t.Fatalf("should not apply with config") 51 } 52 if node.Attributes["driver.lxc"] == "" { 53 t.Fatalf("missing driver") 54 } 55 } 56 57 func TestLxcDriver_Start_Wait(t *testing.T) { 58 if !testutil.IsTravis() { 59 t.Parallel() 60 } 61 if !lxcPresent(t) { 62 t.Skip("lxc not present") 63 } 64 65 task := &structs.Task{ 66 Name: "foo", 67 Driver: "lxc", 68 Config: map[string]interface{}{ 69 "template": "/usr/share/lxc/templates/lxc-busybox", 70 }, 71 KillTimeout: 10 * time.Second, 72 Resources: structs.DefaultResources(), 73 } 74 75 ctx := testDriverContexts(t, task) 76 defer ctx.AllocDir.Destroy() 77 d := NewLxcDriver(ctx.DriverCtx) 78 79 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 80 t.Fatalf("prestart err: %v", err) 81 } 82 sresp, err := d.Start(ctx.ExecCtx, task) 83 if err != nil { 84 t.Fatalf("err: %v", err) 85 } 86 87 lxcHandle, _ := sresp.Handle.(*lxcDriverHandle) 88 89 // Destroy the container after the test 90 defer func() { 91 lxcHandle.container.Stop() 92 lxcHandle.container.Destroy() 93 }() 94 95 testutil.WaitForResult(func() (bool, error) { 96 state := lxcHandle.container.State() 97 if state == lxc.RUNNING { 98 return true, nil 99 } 100 return false, fmt.Errorf("container in state: %v", state) 101 }, func(err error) { 102 t.Fatalf("err: %v", err) 103 }) 104 105 // Look for mounted directories in their proper location 106 containerName := fmt.Sprintf("%s-%s", task.Name, ctx.DriverCtx.allocID) 107 for _, mnt := range []string{"alloc", "local", "secrets"} { 108 fullpath := filepath.Join(lxcHandle.lxcPath, containerName, "rootfs", mnt) 109 stat, err := os.Stat(fullpath) 110 if err != nil { 111 t.Fatalf("err %v", err) 112 } 113 if !stat.IsDir() { 114 t.Fatalf("expected %q to be a dir", fullpath) 115 } 116 } 117 118 // Desroy the container 119 if err := sresp.Handle.Kill(); err != nil { 120 t.Fatalf("err: %v", err) 121 } 122 123 select { 124 case res := <-sresp.Handle.WaitCh(): 125 if !res.Successful() { 126 t.Fatalf("err: %v", res) 127 } 128 case <-time.After(time.Duration(testutil.TestMultiplier()*5) * time.Second): 129 t.Fatalf("timeout") 130 } 131 } 132 133 func TestLxcDriver_Open_Wait(t *testing.T) { 134 if !testutil.IsTravis() { 135 t.Parallel() 136 } 137 if !lxcPresent(t) { 138 t.Skip("lxc not present") 139 } 140 141 task := &structs.Task{ 142 Name: "foo", 143 Driver: "lxc", 144 Config: map[string]interface{}{ 145 "template": "/usr/share/lxc/templates/lxc-busybox", 146 }, 147 KillTimeout: 10 * time.Second, 148 Resources: structs.DefaultResources(), 149 } 150 151 ctx := testDriverContexts(t, task) 152 defer ctx.AllocDir.Destroy() 153 d := NewLxcDriver(ctx.DriverCtx) 154 155 if _, err := d.Prestart(ctx.ExecCtx, task); err != nil { 156 t.Fatalf("prestart err: %v", err) 157 } 158 sresp, err := d.Start(ctx.ExecCtx, task) 159 if err != nil { 160 t.Fatalf("err: %v", err) 161 } 162 163 // Destroy the container after the test 164 lh := sresp.Handle.(*lxcDriverHandle) 165 defer func() { 166 lh.container.Stop() 167 lh.container.Destroy() 168 }() 169 170 handle2, err := d.Open(ctx.ExecCtx, lh.ID()) 171 if err != nil { 172 t.Fatalf("err: %v", err) 173 } 174 175 if handle2 == nil { 176 t.Fatalf("missing handle on open") 177 } 178 179 lxcHandle, _ := handle2.(*lxcDriverHandle) 180 181 testutil.WaitForResult(func() (bool, error) { 182 state := lxcHandle.container.State() 183 if state == lxc.RUNNING { 184 return true, nil 185 } 186 return false, fmt.Errorf("container in state: %v", state) 187 }, func(err error) { 188 t.Fatalf("err: %v", err) 189 }) 190 191 // Desroy the container 192 if err := handle2.Kill(); err != nil { 193 t.Fatalf("err: %v", err) 194 } 195 } 196 197 func lxcPresent(t *testing.T) bool { 198 return lxc.Version() != "" 199 }