Browse code

Extract volume bind, creation and external methods.

Make Start() slightly more readable.

Paul Nasrat authored on 2013/12/04 07:47:49
Showing 1 changed files
... ...
@@ -541,160 +541,18 @@ func (container *Container) Start() (err error) {
541 541
 		log.Printf("WARNING: IPv4 forwarding is disabled. Networking will not work")
542 542
 	}
543 543
 
544
-	// Create the requested bind mounts
545
-	binds := make(map[string]BindMap)
546
-	// Define illegal container destinations
547
-	illegalDsts := []string{"/", "."}
548
-
549
-	for _, bind := range container.hostConfig.Binds {
550
-		// FIXME: factorize bind parsing in parseBind
551
-		var src, dst, mode string
552
-		arr := strings.Split(bind, ":")
553
-		if len(arr) == 2 {
554
-			src = arr[0]
555
-			dst = arr[1]
556
-			mode = "rw"
557
-		} else if len(arr) == 3 {
558
-			src = arr[0]
559
-			dst = arr[1]
560
-			mode = arr[2]
561
-		} else {
562
-			return fmt.Errorf("Invalid bind specification: %s", bind)
563
-		}
564
-
565
-		// Bail if trying to mount to an illegal destination
566
-		for _, illegal := range illegalDsts {
567
-			if dst == illegal {
568
-				return fmt.Errorf("Illegal bind destination: %s", dst)
569
-			}
570
-		}
571
-
572
-		bindMap := BindMap{
573
-			SrcPath: src,
574
-			DstPath: dst,
575
-			Mode:    mode,
576
-		}
577
-		binds[path.Clean(dst)] = bindMap
578
-	}
579
-
580 544
 	if container.Volumes == nil || len(container.Volumes) == 0 {
581 545
 		container.Volumes = make(map[string]string)
582 546
 		container.VolumesRW = make(map[string]bool)
583 547
 	}
584 548
 
585 549
 	// Apply volumes from another container if requested
586
-	container.joinVolumes()
587
-
588
-	volumesDriver := container.runtime.volumes.driver
589
-	// Create the requested volumes if they don't exist
590
-	for volPath := range container.Config.Volumes {
591
-		volPath = path.Clean(volPath)
592
-		volIsDir := true
593
-		// Skip existing volumes
594
-		if _, exists := container.Volumes[volPath]; exists {
595
-			continue
596
-		}
597
-		var srcPath string
598
-		var isBindMount bool
599
-		srcRW := false
600
-		// If an external bind is defined for this volume, use that as a source
601
-		if bindMap, exists := binds[volPath]; exists {
602
-			isBindMount = true
603
-			srcPath = bindMap.SrcPath
604
-			if strings.ToLower(bindMap.Mode) == "rw" {
605
-				srcRW = true
606
-			}
607
-			if file, err := os.Open(bindMap.SrcPath); err != nil {
608
-				return err
609
-			} else {
610
-				defer file.Close()
611
-				if stat, err := file.Stat(); err != nil {
612
-					return err
613
-				} else {
614
-					volIsDir = stat.IsDir()
615
-				}
616
-			}
617
-			// Otherwise create an directory in $ROOT/volumes/ and use that
618
-		} else {
619
-
620
-			// Do not pass a container as the parameter for the volume creation.
621
-			// The graph driver using the container's information ( Image ) to
622
-			// create the parent.
623
-			c, err := container.runtime.volumes.Create(nil, nil, "", "", nil)
624
-			if err != nil {
625
-				return err
626
-			}
627
-			srcPath, err = volumesDriver.Get(c.ID)
628
-			if err != nil {
629
-				return fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", volumesDriver, c.ID, err)
630
-			}
631
-			srcRW = true // RW by default
632
-		}
633
-		container.Volumes[volPath] = srcPath
634
-		container.VolumesRW[volPath] = srcRW
635
-		// Create the mountpoint
636
-		rootVolPath := path.Join(container.RootfsPath(), volPath)
637
-		if volIsDir {
638
-			if err := os.MkdirAll(rootVolPath, 0755); err != nil {
639
-				return err
640
-			}
641
-		}
642
-
643
-		volPath = path.Join(container.RootfsPath(), volPath)
644
-		if _, err := os.Stat(volPath); err != nil {
645
-			if os.IsNotExist(err) {
646
-				if volIsDir {
647
-					if err := os.MkdirAll(volPath, 0755); err != nil {
648
-						return err
649
-					}
650
-				} else {
651
-					if err := os.MkdirAll(path.Dir(volPath), 0755); err != nil {
652
-						return err
653
-					}
654
-					if f, err := os.OpenFile(volPath, os.O_CREATE, 0755); err != nil {
655
-						return err
656
-					} else {
657
-						f.Close()
658
-					}
659
-				}
660
-			}
661
-		}
662
-
663
-		// Do not copy or change permissions if we are mounting from the host
664
-		if srcRW && !isBindMount {
665
-			volList, err := ioutil.ReadDir(rootVolPath)
666
-			if err != nil {
667
-				return err
668
-			}
669
-			if len(volList) > 0 {
670
-				srcList, err := ioutil.ReadDir(srcPath)
671
-				if err != nil {
672
-					return err
673
-				}
674
-				if len(srcList) == 0 {
675
-					// If the source volume is empty copy files from the root into the volume
676
-					if err := archive.CopyWithTar(rootVolPath, srcPath); err != nil {
677
-						return err
678
-					}
550
+	if err := container.applyExternalVolumes(); err != nil {
551
+		return err
552
+	}
679 553
 
680
-					var stat syscall.Stat_t
681
-					if err := syscall.Stat(rootVolPath, &stat); err != nil {
682
-						return err
683
-					}
684
-					var srcStat syscall.Stat_t
685
-					if err := syscall.Stat(srcPath, &srcStat); err != nil {
686
-						return err
687
-					}
688
-					// Change the source volume's ownership if it differs from the root
689
-					// files that where just copied
690
-					if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
691
-						if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
692
-							return err
693
-						}
694
-					}
695
-				}
696
-			}
697
-		}
554
+	if err := container.createVolumes(); err != nil {
555
+		return err
698 556
 	}
699 557
 
700 558
 	if err := container.generateLXCConfig(); err != nil {
... ...
@@ -880,7 +738,165 @@ func (container *Container) Start() (err error) {
880 880
 	return ErrContainerStart
881 881
 }
882 882
 
883
-func (container *Container) joinVolumes() error {
883
+func (container *Container) getBindMap() (map[string]BindMap, error) {
884
+	// Create the requested bind mounts
885
+	binds := make(map[string]BindMap)
886
+	// Define illegal container destinations
887
+	illegalDsts := []string{"/", "."}
888
+
889
+	for _, bind := range container.hostConfig.Binds {
890
+		// FIXME: factorize bind parsing in parseBind
891
+		var src, dst, mode string
892
+		arr := strings.Split(bind, ":")
893
+		if len(arr) == 2 {
894
+			src = arr[0]
895
+			dst = arr[1]
896
+			mode = "rw"
897
+		} else if len(arr) == 3 {
898
+			src = arr[0]
899
+			dst = arr[1]
900
+			mode = arr[2]
901
+		} else {
902
+			return nil, fmt.Errorf("Invalid bind specification: %s", bind)
903
+		}
904
+
905
+		// Bail if trying to mount to an illegal destination
906
+		for _, illegal := range illegalDsts {
907
+			if dst == illegal {
908
+				return nil, fmt.Errorf("Illegal bind destination: %s", dst)
909
+			}
910
+		}
911
+
912
+		bindMap := BindMap{
913
+			SrcPath: src,
914
+			DstPath: dst,
915
+			Mode:    mode,
916
+		}
917
+		binds[path.Clean(dst)] = bindMap
918
+	}
919
+  return binds, nil
920
+}
921
+
922
+func (container *Container) createVolumes() error {
923
+  binds, err := container.getBindMap()
924
+  if err != nil {
925
+    return err
926
+  }
927
+	volumesDriver := container.runtime.volumes.driver
928
+	// Create the requested volumes if they don't exist
929
+	for volPath := range container.Config.Volumes {
930
+		volPath = path.Clean(volPath)
931
+		volIsDir := true
932
+		// Skip existing volumes
933
+		if _, exists := container.Volumes[volPath]; exists {
934
+			continue
935
+		}
936
+		var srcPath string
937
+		var isBindMount bool
938
+		srcRW := false
939
+		// If an external bind is defined for this volume, use that as a source
940
+		if bindMap, exists := binds[volPath]; exists {
941
+			isBindMount = true
942
+			srcPath = bindMap.SrcPath
943
+			if strings.ToLower(bindMap.Mode) == "rw" {
944
+				srcRW = true
945
+			}
946
+			if file, err := os.Open(bindMap.SrcPath); err != nil {
947
+				return err
948
+			} else {
949
+				defer file.Close()
950
+				if stat, err := file.Stat(); err != nil {
951
+					return err
952
+				} else {
953
+					volIsDir = stat.IsDir()
954
+				}
955
+			}
956
+			// Otherwise create an directory in $ROOT/volumes/ and use that
957
+		} else {
958
+
959
+			// Do not pass a container as the parameter for the volume creation.
960
+			// The graph driver using the container's information ( Image ) to
961
+			// create the parent.
962
+			c, err := container.runtime.volumes.Create(nil, nil, "", "", nil)
963
+			if err != nil {
964
+				return err
965
+			}
966
+			srcPath, err = volumesDriver.Get(c.ID)
967
+			if err != nil {
968
+				return fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", volumesDriver, c.ID, err)
969
+			}
970
+			srcRW = true // RW by default
971
+		}
972
+		container.Volumes[volPath] = srcPath
973
+		container.VolumesRW[volPath] = srcRW
974
+		// Create the mountpoint
975
+		rootVolPath := path.Join(container.RootfsPath(), volPath)
976
+		if volIsDir {
977
+			if err := os.MkdirAll(rootVolPath, 0755); err != nil {
978
+				return err
979
+			}
980
+		}
981
+
982
+		volPath = path.Join(container.RootfsPath(), volPath)
983
+		if _, err := os.Stat(volPath); err != nil {
984
+			if os.IsNotExist(err) {
985
+				if volIsDir {
986
+					if err := os.MkdirAll(volPath, 0755); err != nil {
987
+						return err
988
+					}
989
+				} else {
990
+					if err := os.MkdirAll(path.Dir(volPath), 0755); err != nil {
991
+						return err
992
+					}
993
+					if f, err := os.OpenFile(volPath, os.O_CREATE, 0755); err != nil {
994
+						return err
995
+					} else {
996
+						f.Close()
997
+					}
998
+				}
999
+			}
1000
+		}
1001
+
1002
+		// Do not copy or change permissions if we are mounting from the host
1003
+		if srcRW && !isBindMount {
1004
+			volList, err := ioutil.ReadDir(rootVolPath)
1005
+			if err != nil {
1006
+				return err
1007
+			}
1008
+			if len(volList) > 0 {
1009
+				srcList, err := ioutil.ReadDir(srcPath)
1010
+				if err != nil {
1011
+					return err
1012
+				}
1013
+				if len(srcList) == 0 {
1014
+					// If the source volume is empty copy files from the root into the volume
1015
+					if err := archive.CopyWithTar(rootVolPath, srcPath); err != nil {
1016
+						return err
1017
+					}
1018
+
1019
+					var stat syscall.Stat_t
1020
+					if err := syscall.Stat(rootVolPath, &stat); err != nil {
1021
+						return err
1022
+					}
1023
+					var srcStat syscall.Stat_t
1024
+					if err := syscall.Stat(srcPath, &srcStat); err != nil {
1025
+						return err
1026
+					}
1027
+					// Change the source volume's ownership if it differs from the root
1028
+					// files that where just copied
1029
+					if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
1030
+						if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
1031
+							return err
1032
+						}
1033
+					}
1034
+				}
1035
+			}
1036
+		}
1037
+	}
1038
+	return nil
1039
+}
1040
+
1041
+func (container *Container) applyExternalVolumes() error {
884 1042
 	if container.Config.VolumesFrom != "" {
885 1043
 		containerSpecs := strings.Split(container.Config.VolumesFrom, ",")
886 1044
 		for _, containerSpec := range containerSpecs {
... ...
@@ -917,6 +933,7 @@ func (container *Container) joinVolumes() error {
917 917
 
918 918
 		}
919 919
 	}
920
+	return nil
920 921
 }
921 922
 
922 923
 func (container *Container) Run() error {