github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/integration/lifecycle/nesting_test.go (about)

     1  package lifecycle_test
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"log"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	. "github.com/onsi/ginkgo"
    11  	. "github.com/onsi/gomega"
    12  	"github.com/onsi/gomega/gbytes"
    13  	"github.com/onsi/gomega/gexec"
    14  
    15  	"github.com/cloudfoundry-incubator/garden"
    16  	gclient "github.com/cloudfoundry-incubator/garden/client"
    17  	gconn "github.com/cloudfoundry-incubator/garden/client/connection"
    18  )
    19  
    20  var _ = Describe("When nested", func() {
    21  	nestedRootfsPath := os.Getenv("GARDEN_NESTABLE_TEST_ROOTFS")
    22  	if nestedRootfsPath == "" {
    23  		log.Println("GARDEN_NESTABLE_TEST_ROOTFS undefined; skipping nesting test")
    24  		return
    25  	}
    26  
    27  	BeforeEach(func() {
    28  		client = startGarden()
    29  	})
    30  
    31  	startNestedGarden := func(mountOverlayOnTmpfs bool) (garden.Container, string) {
    32  		absoluteBinPath, err := filepath.Abs(binPath)
    33  		Expect(err).ToNot(HaveOccurred())
    34  
    35  		container, err := client.Create(garden.ContainerSpec{
    36  			RootFSPath: nestedRootfsPath,
    37  			// only privileged containers support nesting
    38  			Privileged: true,
    39  			BindMounts: []garden.BindMount{
    40  				{
    41  					SrcPath: filepath.Dir(gardenBin),
    42  					DstPath: "/home/vcap/bin/",
    43  					Mode:    garden.BindMountModeRO,
    44  				},
    45  				{
    46  					SrcPath: absoluteBinPath,
    47  					DstPath: "/home/vcap/binpath/bin",
    48  					Mode:    garden.BindMountModeRO,
    49  				},
    50  				{
    51  					SrcPath: filepath.Join(absoluteBinPath, "..", "skeleton"),
    52  					DstPath: "/home/vcap/binpath/skeleton",
    53  					Mode:    garden.BindMountModeRO,
    54  				},
    55  				{
    56  					SrcPath: rootFSPath,
    57  					DstPath: "/home/vcap/rootfs",
    58  					Mode:    garden.BindMountModeRO,
    59  				},
    60  			},
    61  		})
    62  		Expect(err).ToNot(HaveOccurred())
    63  
    64  		nestedServerOutput := gbytes.NewBuffer()
    65  
    66  		extraMounts := ""
    67  		if mountOverlayOnTmpfs {
    68  			extraMounts = "mount -t tmpfs tmpfs /tmp/overlays"
    69  		}
    70  
    71  		// start nested garden, again need to be root
    72  		_, err = container.Run(garden.ProcessSpec{
    73  			Path: "sh",
    74  			User: "root",
    75  			Dir:  "/home/vcap",
    76  			Args: []string{
    77  				"-c",
    78  				fmt.Sprintf(`
    79  				mkdir /tmp/overlays /tmp/containers /tmp/snapshots /tmp/graph;
    80  				%s
    81  				mount -t tmpfs tmpfs /tmp/containers
    82  
    83  				./bin/garden-linux \
    84  					-bin /home/vcap/binpath/bin \
    85  					-rootfs /home/vcap/rootfs \
    86  					-depot /tmp/containers \
    87  					-overlays /tmp/overlays \
    88  					-snapshots /tmp/snapshots \
    89  					-graph /tmp/graph \
    90  					-disableQuotas \
    91  					-listenNetwork tcp \
    92  					-listenAddr 0.0.0.0:7778;
    93  				`, extraMounts),
    94  			},
    95  		}, garden.ProcessIO{
    96  			Stdout: io.MultiWriter(nestedServerOutput, gexec.NewPrefixedWriter("\x1b[32m[o]\x1b[34m[nested-garden-linux]\x1b[0m ", GinkgoWriter)),
    97  			Stderr: gexec.NewPrefixedWriter("\x1b[91m[e]\x1b[34m[nested-garden-linux]\x1b[0m ", GinkgoWriter),
    98  		})
    99  
   100  		info, err := container.Info()
   101  		Expect(err).ToNot(HaveOccurred())
   102  
   103  		nestedGardenAddress := fmt.Sprintf("%s:7778", info.ContainerIP)
   104  		Eventually(nestedServerOutput, "30s").Should(gbytes.Say("garden-linux.started"))
   105  
   106  		return container, nestedGardenAddress
   107  	}
   108  
   109  	It("can start a nested garden-linux and run a container inside it", func() {
   110  		container, nestedGardenAddress := startNestedGarden(true)
   111  		defer client.Destroy(container.Handle())
   112  
   113  		nestedClient := gclient.New(gconn.New("tcp", nestedGardenAddress))
   114  		nestedContainer, err := nestedClient.Create(garden.ContainerSpec{})
   115  		Expect(err).ToNot(HaveOccurred())
   116  
   117  		nestedOutput := gbytes.NewBuffer()
   118  		_, err = nestedContainer.Run(garden.ProcessSpec{
   119  			Path: "/bin/echo",
   120  			Args: []string{
   121  				"I am nested!",
   122  			},
   123  		}, garden.ProcessIO{Stdout: nestedOutput, Stderr: nestedOutput})
   124  		Expect(err).ToNot(HaveOccurred())
   125  
   126  		Eventually(nestedOutput, "30s").Should(gbytes.Say("I am nested!"))
   127  	})
   128  
   129  	It("returns helpful error message when depot directory fstype cannot be nested", func() {
   130  		container, nestedGardenAddress := startNestedGarden(false)
   131  		defer client.Destroy(container.Handle())
   132  
   133  		nestedClient := gclient.New(gconn.New("tcp", nestedGardenAddress))
   134  		_, err := nestedClient.Create(garden.ContainerSpec{})
   135  		Expect(err).To(MatchError("overlay.sh: exit status 222, the directories that contain the depot and rootfs must be mounted on a filesystem type that supports aufs or overlayfs"))
   136  	})
   137  })