Skip to content

Commit

Permalink
Merge pull request #167 from tmjd/fixing-pins
Browse files Browse the repository at this point in the history
Fixing pins
  • Loading branch information
bcreane authored Nov 22, 2017
2 parents 05f23ea + 0086d7a commit dac3a40
Show file tree
Hide file tree
Showing 15 changed files with 563 additions and 186 deletions.
34 changes: 34 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!--- Provide a general summary of the issue in the Title above -->

## Expected Behavior
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->

## Current Behavior
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->

## Possible Solution
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
<!--- or ideas how to implement the addition or change -->

## Steps to Reproduce (for bugs)
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. Include code to reproduce, if relevant -->
1.
2.
3.
4.

## Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->

## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Docker version:
* Libnetwork-plugin version:
* How you deployed the libnetwork plugin:
* Operating System and version:
* Link to your project (optional):

12 changes: 12 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Description
A few sentences describing the overall goals of the pull request's commits.
Please include
- the type of fix - (e.g. bug fix, new feature, documentation)
- some details on _why_ this PR should be merged
- the details of the testing you've done on it (both manual and automated)
- which components are affected by this PR

## Todos
- [ ] Tests
- [ ] Documentation

35 changes: 11 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@
# considerably.
.SUFFIXES:

GO_BUILD_VER?=v0.8

SRC_FILES=$(shell find . -type f -name '*.go')

# These variables can be overridden by setting an environment variable.
LOCAL_IP_ENV?=$(shell ip route get 8.8.8.8 | head -1 | awk '{print $$7}')

# Can choose different docker versions see list here - https://hub.docker.com/_/docker/
DOCKER_VERSION?=rc-dind
DOCKER_VERSION?=dind
HOST_CHECKOUT_DIR?=$(CURDIR)
CONTAINER_NAME?=calico/libnetwork-plugin
CALICO_BUILD?=calico/go-build:v0.8
GO_BUILD_CONTAINER?=calico/go-build:$(GO_BUILD_VER)
PLUGIN_LOCATION?=$(CURDIR)/dist/libnetwork-plugin
DOCKER_BINARY_CONTAINER?=docker-binary-container

# To run with non-native docker (e.g. on Windows or OSX) you might need to overide these variables
# To run with non-native docker (e.g. on Windows or OSX) you might need to overide this variable
LOCAL_USER_ID?=$(shell id -u $$USER)
LOCAL_GROUP_ID?=$(shell getent group docker | cut -d: -f3)

default: all
all: test
Expand All @@ -30,7 +31,7 @@ vendor: glide.yaml
-v $(CURDIR):/go/src/github.com/projectcalico/libnetwork-plugin:rw \
-v $(HOME)/.glide:/home/user/.glide:rw \
-e LOCAL_USER_ID=$(LOCAL_USER_ID) \
$(CALICO_BUILD) /bin/sh -c ' \
$(GO_BUILD_CONTAINER) /bin/sh -c ' \
cd /go/src/github.com/projectcalico/libnetwork-plugin && \
glide install -strip-vendor'

Expand All @@ -46,7 +47,7 @@ dist/libnetwork-plugin: vendor
-v $(CURDIR)/dist:/go/src/github.com/projectcalico/libnetwork-plugin/dist \
-v $(CURDIR)/.go-pkg-cache:/go/pkg/:rw \
-e LOCAL_USER_ID=$(LOCAL_USER_ID) \
$(CALICO_BUILD) sh -c '\
$(GO_BUILD_CONTAINER) sh -c '\
cd /go/src/github.com/projectcalico/libnetwork-plugin && \
make build'

Expand All @@ -67,35 +68,22 @@ static-checks: vendor
gometalinter --deadline=30s --disable-all --enable=goimports --enable=vet --enable=errcheck --enable=varcheck --enable=unused --enable=dupl $$(glide nv)'

run-etcd:
@-docker rm -f calico-etcd calico-etcd-ssl
@-docker rm -f calico-etcd
docker run --detach \
--net=host \
--name calico-etcd quay.io/coreos/etcd \
etcd \
--advertise-client-urls "http://$(LOCAL_IP_ENV):2379,http://127.0.0.1:2379" \
--listen-client-urls "http://0.0.0.0:2379"

semaphore: test-containerized
set -e; \
if [ -z $$PULL_REQUEST_NUMBER ]; then \
$(MAKE) $(CONTAINER_NAME); \
docker tag $(CONTAINER_NAME) $(CONTAINER_NAME):$$BRANCH_NAME && docker push $(CONTAINER_NAME):$$BRANCH_NAME; \
docker tag $(CONTAINER_NAME) quay.io/$(CONTAINER_NAME):$$BRANCH_NAME && docker push quay.io/$(CONTAINER_NAME):$$BRANCH_NAME; \
if [ "$$BRANCH_NAME" = "master" ]; then \
export VERSION=`git describe --tags --dirty`; \
docker tag $(CONTAINER_NAME) $(CONTAINER_NAME):$$VERSION && docker push $(CONTAINER_NAME):$$VERSION; \
docker tag $(CONTAINER_NAME) quay.io/$(CONTAINER_NAME):$$VERSION && docker push quay.io/$(CONTAINER_NAME):$$VERSION; \
fi; \
fi

release: clean
ifndef VERSION
$(error VERSION is undefined - run using make release VERSION=vX.Y.Z)
endif
git tag $(VERSION)
$(MAKE) $(CONTAINER_NAME)
# Check that the version output appears on a line of its own (the -x option to grep).
# Tests that the "git tag" makes it into the binary. Main point is to catch "-dirty" builds
# Tests that the "git tag" makes it into the binary. Main point is to catch "-dirty" builds
@echo "Checking if the tag made it into the binary"
docker run --rm calico/libnetwork-plugin -v | grep -x $(VERSION) || (echo "Reported version:" `docker run --rm calico/libnetwork-plugin -v` "\nExpected version: $(VERSION)" && exit 1)
docker tag calico/libnetwork-plugin calico/libnetwork-plugin:$(VERSION)
Expand All @@ -120,6 +108,7 @@ run-plugin: run-etcd dist/libnetwork-plugin
-v $(PLUGIN_LOCATION):/libnetwork-plugin \
docker:$(DOCKER_VERSION) --cluster-store=etcd://$(LOCAL_IP_ENV):2379
# View the logs by running 'docker exec dind cat plugin.log'
docker exec -tid --privileged dind sh -c 'sysctl -w net.ipv6.conf.default.disable_ipv6=0'
docker exec -tid --privileged dind sh -c '/libnetwork-plugin 2>>/plugin.log'
# To speak to this docker:
# export DOCKER_HOST=localhost:5375
Expand All @@ -137,11 +126,9 @@ test-containerized: dist/libnetwork-plugin
docker run -ti --rm --net=host \
-v $(CURDIR):/go/src/github.com/projectcalico/libnetwork-plugin \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(CURDIR)/.go-pkg-cache:/go/pkg/:rw \
-v $(CURDIR)/docker:/usr/bin/docker \
-e PLUGIN_LOCATION=$(CURDIR)/dist/libnetwork-plugin \
-e EXTRA_GROUP_ID=$(LOCAL_GROUP_ID) \
-e LOCAL_USER_ID=$(LOCAL_USER_ID) \
-e LOCAL_USER_ID=0 \
calico/go-build sh -c '\
cd /go/src/github.com/projectcalico/libnetwork-plugin && \
make test'
Expand Down
83 changes: 79 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@
# Libnetwork plugin for Calico

This plugin for Docker networking ([libnetwork](https://github.com/docker/libnetwork)) is intended for use with [Project Calico](http://www.projectcalico.org).
The plugin is integrated with the `calico/node` image which is created from the [calico-containers](https://github.com/projectcalico/calico-containers) repository.
The plugin is integrated with the `calico/node` image which is created from the [calicoctl](https://github.com/projectcalico/calicoctl) repository, but it can also be run in it's own Docker container or as a standalone binary.

Guides on how to get started with the plugin and further documentation is available from http://docs.projectcalico.org

The remaining information is for advanced users.
## Supported options for confguration

## How to Run It
### Working with Networks
* When creating a network, the `--subnet` option can be passed to `docker network create`. The subnet must match an existing Calico pool, and any containers created on that network will use an IP address from that Calico Pool.
* Other than `--driver` and `--ipam-driver`, no other options are supported on the `docker network create` command.

### Working with Containers
When creating containers, use the `--net` option to connect them to a network previously created with `docker network create`

* The `--ip` option can be passed to `docker run` to assign a specific IP to a container.
* The `--mac` and `--link-local` options are currently unsupported.

## Working with the code

* Clone the repo (clone it into your GOPATH and make sure you use projectcalico in the path, not your fork name).
* Create the vendor directory (`make vendor`). This uses `glide` in a docker container to create the vendor directory.
* Build it in a container using `make dist/libnetwork-plugin`. The plugin binary will appear in the `dist` directory.
* Running tests can be done in a container using `make test-containerized`. Note: This works on linux, but can require additional steps on Mac.
* Submit PRs through GitHub. Before merging, you'll be asked to squash your commits together, so 1 PR = 1 commit.
* Before submitting your PR, please make sure tests pass and run `make static-checks`. Both these will be done by the CI system too though.

## How to Run It During Development
`make run-plugin`

Running the plugin in a container requires a few specific options
Expand All @@ -34,14 +53,70 @@ On OSX/Windows you can't run Docker natively. To allow the Makefile to write the
Run `make test` like this: `LOCAL_USER_ID=1000 LOCAL_GROUP_ID=100 make test-containerized`



## IPv6 Usage

*Note: IPv4 can't be disabled, IPv6 is enabled in addition to IPv4.*

Docker IPv6 support must be enabled e.g.
```
dockerd --cluster-store=etcd://127.0.0.1:2379 --ipv6 --fixed-cidr-v6="2001:db8:1::/64"
```

### Start the libnetwork-plugin

```
sudo dist/libnetwork-plugin
```

### Add an IPv6 address to the host

```
sudo ip addr add fd80:24e2:f998:72d7::1/112 dev eth1
```

### Start calico/node, without using the calico/node libnetwork-plugin, also pass in the host IPv6 address

```
sudo calicoctl node run --disable-docker-networking --ip6=fd80:24e2:f998:72d7::1
```

### Create an IPv6 network

```
docker network create --ipv6 -d calico --ipam-driver calico-ipam my_net
```

### Run containers on the IPv6 network

```
docker run --net my_net --name workload-A -tid busybox
docker run --net my_net --name workload-B -tid busybox
```


### Check IPv6 network connectivity

```
docker exec workload-A ping -6 -c 4 workload-B.my_net
docker exec workload-B ping -6 -c 4 workload-A.my_net
```

### Check IPv4 network connectivity

```
docker exec workload-A ping -4 -c 4 workload-B.my_net
docker exec workload-B ping -4 -c 4 workload-A.my_net
```


## Known limitations
The following is a list of known limitations when using the Calico libnetwork
driver:
- It is not possible to add multiple networks to a single container. However,
once a container endpoint is created, it is possible to manually add
additional Calico profiles to that endpoint (effectively adding the
container into another network).
- IPv6 is not currently supported

## Configuring

Expand Down
65 changes: 47 additions & 18 deletions driver/ipam_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"fmt"
"net"

log "github.com/Sirupsen/logrus"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"

"github.com/docker/go-plugins-helpers/ipam"
"github.com/projectcalico/libcalico-go/lib/api"
Expand Down Expand Up @@ -66,17 +66,21 @@ func (i IpamDriver) RequestPool(request *ipam.RequestPoolRequest) (*ipam.Request
log.Errorln(err)
return nil, err
}

var poolID string
var pool string
var gateway string
if request.V6 {
err := errors.New("IPv6 isn't supported")
log.Errorln(err)
return nil, err
// Default the poolID to the fixed value.
poolID = i.poolIDV6
pool = "::/0"
gateway = "::/0"
} else {
// Default the poolID to the fixed value.
poolID = i.poolIDV4
pool = "0.0.0.0/0"
gateway = "0.0.0.0/0"
}

// Default the poolID to the fixed value.
poolID := i.poolIDV4
pool := "0.0.0.0/0"

// If a pool (subnet on the CLI) is specified, it must match one of the
// preconfigured Calico pools.
if request.Pool != "" {
Expand Down Expand Up @@ -107,7 +111,7 @@ func (i IpamDriver) RequestPool(request *ipam.RequestPoolRequest) (*ipam.Request
resp := &ipam.RequestPoolResponse{
PoolID: poolID,
Pool: pool,
Data: map[string]string{"com.docker.network.gateway": "0.0.0.0/0"},
Data: map[string]string{"com.docker.network.gateway": gateway},
}

logutils.JSONMessage("RequestPool response", resp)
Expand Down Expand Up @@ -145,10 +149,20 @@ func (i IpamDriver) RequestAddress(request *ipam.RequestAddressRequest) (*ipam.R
// If the poolID isn't the fixed one then find the pool to assign from.
// poolV4 defaults to nil to assign from across all pools.
var poolV4 []caliconet.IPNet
if request.PoolID != PoolIDV4 {

var poolV6 []caliconet.IPNet
var numIPv4, numIPv6, version int
if request.PoolID == PoolIDV4 {
version = 4
numIPv4 = 1
numIPv6 = 0
} else if request.PoolID == PoolIDV6 {
version = 6
numIPv4 = 0
numIPv6 = 1
} else {
poolsClient := i.client.IPPools()
_, ipNet, err := caliconet.ParseCIDR(request.PoolID)

if err != nil {
err = errors.Wrapf(err, "Invalid CIDR - %v", request.PoolID)
log.Errorln(err)
Expand All @@ -162,19 +176,26 @@ func (i IpamDriver) RequestAddress(request *ipam.RequestAddressRequest) (*ipam.R
log.Errorln(err)
return nil, err
}
poolV4 = []caliconet.IPNet{caliconet.IPNet{IPNet: pool.Metadata.CIDR.IPNet}}
log.Debugln("Using specific pool ", poolV4)
version = ipNet.Version()
if version == 4 {
poolV4 = []caliconet.IPNet{caliconet.IPNet{IPNet: pool.Metadata.CIDR.IPNet}}
log.Debugln("Using specific pool ", poolV4)
} else if version == 6 {
poolV6 = []caliconet.IPNet{caliconet.IPNet{IPNet: pool.Metadata.CIDR.IPNet}}
log.Debugln("Using specific pool ", poolV6)
}
}

// Auto assign an IP address.
// IPv4 pool will be nil if the docker network doesn't have a subnet associated with.
// IPv4/v6 pool will be nil if the docker network doesn't have a subnet associated with.
// Otherwise, it will be set to the Calico pool to assign from.
IPsV4, IPsV6, err := i.client.IPAM().AutoAssign(
datastoreClient.AutoAssignArgs{
Num4: 1,
Num6: 0,
Num4: numIPv4,
Num6: numIPv6,
Hostname: hostname,
IPv4Pools: poolV4,
IPv6Pools: poolV6,
},
)

Expand Down Expand Up @@ -212,8 +233,16 @@ func (i IpamDriver) RequestAddress(request *ipam.RequestAddressRequest) (*ipam.R
}

// Return the IP as a CIDR.
var respAddr string
if IPs[0].Version() == 4 {
// IPv4 address
respAddr = fmt.Sprintf("%v/%v", IPs[0], "32")
} else {
// IPv6 address
respAddr = fmt.Sprintf("%v/%v", IPs[0], "128")
}
resp := &ipam.RequestAddressResponse{
Address: fmt.Sprintf("%v/%v", IPs[0], "32"),
Address: respAddr,
}

logutils.JSONMessage("RequestAddress response", resp)
Expand Down
Loading

0 comments on commit dac3a40

Please sign in to comment.