Browse code

Check kernel version and display warning if too low

Guillaume J. Charmes authored on 2013/04/19 12:47:24
Showing 2 changed files
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"github.com/dotcloud/docker/auth"
7 7
 	"io"
8 8
 	"io/ioutil"
9
+	"log"
9 10
 	"os"
10 11
 	"os/exec"
11 12
 	"path"
... ...
@@ -23,6 +24,7 @@ type Runtime struct {
23 23
 	repositories   *TagStore
24 24
 	authConfig     *auth.AuthConfig
25 25
 	idIndex        *TruncIndex
26
+	kernelVersion  *KernelVersionInfo
26 27
 }
27 28
 
28 29
 var sysInitPath string
... ...
@@ -282,7 +284,22 @@ func (runtime *Runtime) restore() error {
282 282
 
283 283
 // FIXME: harmonize with NewGraph()
284 284
 func NewRuntime() (*Runtime, error) {
285
-	return NewRuntimeFromDirectory("/var/lib/docker")
285
+	runtime, err := NewRuntimeFromDirectory("/var/lib/docker")
286
+	if err != nil {
287
+		return nil, err
288
+	}
289
+
290
+	k, err := GetKernelVersion()
291
+	if err != nil {
292
+		return nil, err
293
+	}
294
+	runtime.kernelVersion = k
295
+
296
+	if CompareKernelVersion(k, &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 {
297
+		log.Printf("WARNING: You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String())
298
+	}
299
+
300
+	return runtime, nil
286 301
 }
287 302
 
288 303
 func NewRuntimeFromDirectory(root string) (*Runtime, error) {
... ...
@@ -13,8 +13,10 @@ import (
13 13
 	"os/exec"
14 14
 	"path/filepath"
15 15
 	"runtime"
16
+	"strconv"
16 17
 	"strings"
17 18
 	"sync"
19
+	"syscall"
18 20
 	"time"
19 21
 )
20 22
 
... ...
@@ -384,3 +386,95 @@ func CopyEscapable(dst io.Writer, src io.ReadCloser) (written int64, err error)
384 384
 	}
385 385
 	return written, err
386 386
 }
387
+
388
+type KernelVersionInfo struct {
389
+	Kernel   int
390
+	Major    int
391
+	Minor    int
392
+	Specific int
393
+}
394
+
395
+func GetKernelVersion() (*KernelVersionInfo, error) {
396
+	var uts syscall.Utsname
397
+
398
+	if err := syscall.Uname(&uts); err != nil {
399
+		return nil, err
400
+	}
401
+
402
+	release := make([]byte, len(uts.Release))
403
+
404
+	i := 0
405
+	for _, c := range uts.Release {
406
+		release[i] = byte(c)
407
+		i++
408
+	}
409
+
410
+	tmp := strings.SplitN(string(release), "-", 2)
411
+	if len(tmp) != 2 {
412
+		return nil, fmt.Errorf("Unrecognized kernel version")
413
+	}
414
+	tmp2 := strings.SplitN(tmp[0], ".", 3)
415
+	if len(tmp2) != 3 {
416
+		return nil, fmt.Errorf("Unrecognized kernel version")
417
+	}
418
+
419
+	kernel, err := strconv.Atoi(tmp2[0])
420
+	if err != nil {
421
+		return nil, err
422
+	}
423
+
424
+	major, err := strconv.Atoi(tmp2[1])
425
+	if err != nil {
426
+		return nil, err
427
+	}
428
+
429
+	minor, err := strconv.Atoi(tmp2[2])
430
+	if err != nil {
431
+		return nil, err
432
+	}
433
+
434
+	specific, err := strconv.Atoi(strings.Split(tmp[1], "-")[0])
435
+	if err != nil {
436
+		return nil, err
437
+	}
438
+
439
+	return &KernelVersionInfo{
440
+		Kernel:   kernel,
441
+		Major:    major,
442
+		Minor:    minor,
443
+		Specific: specific,
444
+	}, nil
445
+}
446
+
447
+func (k *KernelVersionInfo) String() string {
448
+	return fmt.Sprintf("%d.%d.%d-%d", k.Kernel, k.Major, k.Minor, k.Specific)
449
+}
450
+
451
+// Compare two KernelVersionInfo struct.
452
+// Returns -1 if a < b, = if a == b, 1 it a > b
453
+func CompareKernelVersion(a, b *KernelVersionInfo) int {
454
+	if a.Kernel < b.Kernel {
455
+		return -1
456
+	} else if a.Kernel > b.Kernel {
457
+		return 1
458
+	}
459
+
460
+	if a.Major < b.Major {
461
+		return -1
462
+	} else if a.Major > b.Major {
463
+		return 1
464
+	}
465
+
466
+	if a.Minor < b.Minor {
467
+		return -1
468
+	} else if a.Minor > b.Minor {
469
+		return 1
470
+	}
471
+
472
+	if a.Specific < b.Specific {
473
+		return -1
474
+	} else if a.Specific > b.Specific {
475
+		return 1
476
+	}
477
+	return 0
478
+}