func NewLibvirtLXCBackend(state *State, vman *volumemanager.Manager, volPath, logPath, initPath string, mux *logmux.LogMux) (Backend, error) {
	libvirtc, err := libvirt.NewVirConnection("lxc:///")
	if err != nil {
		return nil, err
	}

	pinkertonCtx, err := pinkerton.BuildContext("aufs", imageRoot)
	if err != nil {
		return nil, err
	}

	return &LibvirtLXCBackend{
		LogPath:             logPath,
		VolPath:             volPath,
		InitPath:            initPath,
		libvirt:             libvirtc,
		state:               state,
		vman:                vman,
		pinkerton:           pinkertonCtx,
		logs:                make(map[string]*logbuf.Log),
		containers:          make(map[string]*libvirtContainer),
		defaultEnv:          make(map[string]string),
		resolvConf:          "/etc/resolv.conf",
		mux:                 mux,
		ipalloc:             ipallocator.New(),
		discoverdConfigured: make(chan struct{}),
		networkConfigured:   make(chan struct{}),
	}, nil
}
Example #2
0
func build(name string) error {
	name = "flynn/" + name

	cmd := exec.Command("docker", "build", "-t", name, ".")
	cmd.Stdout = os.Stderr
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("error building docker image: %s", err)
	}

	context, err := pinkerton.BuildContext("aufs", "/var/lib/docker")
	if err != nil {
		return err
	}

	layerDir := "/var/lib/flynn/layer-cache"
	if err := os.MkdirAll(layerDir, 0755); err != nil {
		return err
	}

	b := &imagebuilder.Builder{
		Store:   &layerStore{layerDir},
		Context: context,
	}

	manifest, err := b.Build(name, true)
	if err != nil {
		return err
	}
	_, err = os.Stdout.Write(manifest.RawManifest())
	return err
}
Example #3
0
func main() {
	usage := `Pinkerton manages Docker images.

Usage:
  pinkerton pull [options] <image-url>
  pinkerton checkout [options] <id> <image-id>
  pinkerton cleanup [options] <id>
  pinkerton -h | --help

Commands:
  pull      Download a Docker image
  checkout  Create a working copy of an image
  cleanup   Destroy a working copy of an image

Examples:
  pinkerton pull https://registry.hub.docker.com/redis
  pinkerton pull https://registry.hub.docker.com/ubuntu?tag=trusty
  pinkerton pull https://registry.hub.docker.com/flynn/slugrunner?id=1443bd6a675b959693a1a4021d660bebbdbff688d00c65ff057c46702e4b8933
  pinkerton checkout slugrunner-test 1443bd6a675b959693a1a4021d660bebbdbff688d00c65ff057c46702e4b8933
  pinkerton cleanup slugrunner-test

Options:
  -h, --help       show this message and exit
  --driver=<name>  storage driver [default: aufs]
  --root=<path>    storage root [default: /var/lib/docker]
  --json           emit json-formatted output
`

	args, _ := docopt.Parse(usage, nil, true, "", false)

	ctx, err := pinkerton.BuildContext(args.String["--driver"], args.String["--root"])
	if err != nil {
		log.Fatal(err)
	}

	switch {
	case args.Bool["pull"]:
		if err := ctx.Pull(args.String["<image-url>"], pinkerton.InfoPrinter(args.Bool["--json"])); err != nil {
			log.Fatal(err)
		}
	case args.Bool["checkout"]:
		path, err := ctx.Checkout(args.String["<id>"], args.String["<image-id>"])
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println(path)
	case args.Bool["cleanup"]:
		if err := ctx.Cleanup(args.String["<id>"]); err != nil {
			log.Fatal(err)
		}
	}
}
func NewLibvirtLXCBackend(state *State, vman *volumemanager.Manager, bridgeName, initPath, umountPath string, mux *logmux.Mux, partitionCGroups map[string]int64, logger log15.Logger) (Backend, error) {
	libvirtc, err := libvirt.NewVirConnection("lxc:///")
	if err != nil {
		return nil, err
	}

	pinkertonCtx, err := pinkerton.BuildContext("aufs", imageRoot)
	if err != nil {
		return nil, err
	}

	for name, shares := range partitionCGroups {
		if err := createCGroupPartition(name, shares); err != nil {
			return nil, err
		}
	}

	return &LibvirtLXCBackend{
		InitPath:            initPath,
		UmountPath:          umountPath,
		libvirt:             libvirtc,
		state:               state,
		vman:                vman,
		pinkerton:           pinkertonCtx,
		logStreams:          make(map[string]map[string]*logmux.LogStream),
		containers:          make(map[string]*libvirtContainer),
		defaultEnv:          make(map[string]string),
		resolvConf:          "/etc/resolv.conf",
		mux:                 mux,
		ipalloc:             ipallocator.New(),
		bridgeName:          bridgeName,
		discoverdConfigured: make(chan struct{}),
		networkConfigured:   make(chan struct{}),
		partitionCGroups:    partitionCGroups,
		logger:              logger,
	}, nil
}
Example #5
0
func NewLibcontainerBackend(state *State, vman *volumemanager.Manager, bridgeName, initPath string, mux *logmux.Mux, partitionCGroups map[string]int64, logger log15.Logger) (Backend, error) {
	factory, err := libcontainer.New(
		containerRoot,
		libcontainer.Cgroupfs,
		libcontainer.InitArgs(os.Args[0], "libcontainer-init"),
	)

	pinkertonCtx, err := pinkerton.BuildContext("aufs", imageRoot)
	if err != nil {
		return nil, err
	}

	if err := setupCGroups(partitionCGroups); err != nil {
		return nil, err
	}

	return &LibcontainerBackend{
		InitPath:            initPath,
		factory:             factory,
		state:               state,
		vman:                vman,
		pinkerton:           pinkertonCtx,
		logStreams:          make(map[string]map[string]*logmux.LogStream),
		containers:          make(map[string]*Container),
		defaultEnv:          make(map[string]string),
		resolvConf:          "/etc/resolv.conf",
		mux:                 mux,
		ipalloc:             ipallocator.New(),
		bridgeName:          bridgeName,
		discoverdConfigured: make(chan struct{}),
		networkConfigured:   make(chan struct{}),
		partitionCGroups:    partitionCGroups,
		logger:              logger,
		globalState:         &libcontainerGlobalState{},
	}, nil
}
Example #6
0
func runDownload(args *docopt.Args) error {
	if err := os.MkdirAll(args.String["--root"], 0755); err != nil {
		return fmt.Errorf("error creating root dir: %s", err)
	}

	var manifest map[string]string
	if err := cliutil.DecodeJSONArg(args.String["<manifest>"], &manifest); err != nil {
		return err
	}

	ctx, err := pinkerton.BuildContext(args.String["--driver"], args.String["--root"])
	if err != nil {
		return err
	}

	for image, id := range manifest {
		fmt.Printf("Downloading %s %s...\n", image, id)
		image += "?id=" + id
		if err := ctx.Pull(image, pinkerton.InfoPrinter(false)); err != nil {
			return err
		}
	}
	return nil
}
func NewLibvirtLXCBackend(state *State, portAlloc map[string]*ports.Allocator, volPath, logPath, initPath string) (Backend, error) {
	libvirtc, err := libvirt.NewVirConnection("lxc:///")
	if err != nil {
		return nil, err
	}

	pinkertonCtx, err := pinkerton.BuildContext("aufs", "/var/lib/docker")
	if err != nil {
		return nil, err
	}

	if err := writeResolvConf("/etc/flynn/resolv.conf"); err != nil {
		return nil, fmt.Errorf("Could not create resolv.conf: %s", err)
	}

	b := random.Bytes(5)
	bridgeMAC := fmt.Sprintf("fe:%02x:%02x:%02x:%02x:%02x", b[0], b[1], b[2], b[3], b[4])

	network, err := libvirtc.LookupNetworkByName(libvirtNetName)
	if err != nil {
		n := &lt.Network{
			Name:   libvirtNetName,
			Bridge: lt.Bridge{Name: bridgeName, STP: "off"},
			IP:     lt.IP{Address: bridgeAddr.String(), Netmask: bridgeMask},
			MAC:    lt.MAC{Address: bridgeMAC},
		}
		network, err = libvirtc.NetworkDefineXML(string(n.XML()))
		if err != nil {
			return nil, err
		}
	}
	active, err := network.IsActive()
	if err != nil {
		return nil, err
	}
	if !active {
		if err := network.Create(); err != nil {
			return nil, err
		}
	}
	// We need to explicitly assign the MAC address to avoid it changing to a lower value
	// See: https://github.com/flynn/flynn/issues/223
	if err := netlink.NetworkSetMacAddress(bridgeName, bridgeMAC); err != nil {
		return nil, err
	}

	iptables.RemoveExistingChain("FLYNN", bridgeName)
	chain, err := iptables.NewChain("FLYNN", bridgeName)
	if err != nil {
		return nil, err
	}
	if err := ioutil.WriteFile("/proc/sys/net/ipv4/conf/"+bridgeName+"/route_localnet", []byte("1"), 0666); err != nil {
		return nil, err
	}
	return &LibvirtLXCBackend{
		LogPath:    logPath,
		VolPath:    volPath,
		InitPath:   initPath,
		libvirt:    libvirtc,
		state:      state,
		ports:      portAlloc,
		pinkerton:  pinkertonCtx,
		forwarder:  ports.NewForwarder(net.ParseIP("0.0.0.0"), chain),
		logs:       make(map[string]*logbuf.Log),
		containers: make(map[string]*libvirtContainer),
	}, nil
}
Example #8
0
func run(url string) error {
	client, err := controller.NewClient("", os.Getenv("CONTROLLER_KEY"))
	if err != nil {
		return err
	}

	context, err := pinkerton.BuildContext("flynn", "/tmp/docker")
	if err != nil {
		return err
	}

	builder := &imagebuilder.Builder{
		Store:   &layerStore{},
		Context: context,
	}

	// pull the docker image
	ref, err := pinkerton.NewRef(url)
	if err != nil {
		return err
	}
	if _, err := context.PullDocker(url, ioutil.Discard); err != nil {
		return err
	}

	// create squashfs for each layer
	image, err := builder.Build(ref.DockerRef(), false)
	if err != nil {
		return err
	}

	// add the app name to the manifest to change its resulting ID so
	// pushing the same image to multiple apps leads to different artifacts
	// in the controller (and hence distinct artifact events)
	if image.Meta == nil {
		image.Meta = make(map[string]string, 1)
	}
	image.Meta["docker-receive.repository"] = ref.Name()

	// upload manifest to blobstore
	rawManifest := image.RawManifest()
	imageURL := fmt.Sprintf("http://blobstore.discoverd/docker-receive/images/%s.json", image.ID())
	if err := upload(bytes.NewReader(rawManifest), imageURL); err != nil {
		return err
	}

	// create the artifact
	artifact := &ct.Artifact{
		ID:   os.Getenv("ARTIFACT_ID"),
		Type: ct.ArtifactTypeFlynn,
		URI:  imageURL,
		Meta: map[string]string{
			"blobstore":                 "true",
			"docker-receive.uri":        url,
			"docker-receive.repository": ref.Name(),
			"docker-receive.digest":     ref.ID(),
		},
		RawManifest:      rawManifest,
		Hashes:           image.Hashes(),
		Size:             int64(len(rawManifest)),
		LayerURLTemplate: layerURLTemplate,
	}
	return client.CreateArtifact(artifact)
}