Skip to content

Commit

Permalink
Merge pull request #283 from srl-wim/reuse-mgmt-net
Browse files Browse the repository at this point in the history
refactored network reuse
  • Loading branch information
hellt authored Feb 19, 2021
2 parents 88fd19b + 7c8dccc commit fc1a50a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 64 deletions.
123 changes: 63 additions & 60 deletions clab/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,81 +15,84 @@ import (
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
"github.com/google/shlex"
log "github.com/sirupsen/logrus"
)

const sysctlBase = "/proc/sys"

// CreateBridge creates a docker bridge
func (c *CLab) CreateBridge(ctx context.Context) (err error) {
log.Infof("Creating docker network: Name='%s', IPv4Subnet='%s', IPv6Subnet='%s'", c.Config.Mgmt.Network, c.Config.Mgmt.IPv4Subnet, c.Config.Mgmt.IPv6Subnet)

enableIPv6 := false
var ipamConfig []network.IPAMConfig
if c.Config.Mgmt.IPv4Subnet != "" {
ipamConfig = append(ipamConfig, network.IPAMConfig{
Subnet: c.Config.Mgmt.IPv4Subnet,
})
}
if c.Config.Mgmt.IPv6Subnet != "" {
ipamConfig = append(ipamConfig, network.IPAMConfig{
Subnet: c.Config.Mgmt.IPv6Subnet,
})
enableIPv6 = true
}

ipam := &network.IPAM{
Driver: "default",
Config: ipamConfig,
}

networkOptions := types.NetworkCreate{
CheckDuplicate: true,
Driver: "bridge",
EnableIPv6: enableIPv6,
IPAM: ipam,
Internal: false,
Attachable: false,
Labels: map[string]string{
"containerlab": "",
},
Options: map[string]string{
"com.docker.network.driver.mtu": c.Config.Mgmt.MTU,
},
}

var bridgeName string
var netCreateResponse types.NetworkCreateResponse
// CreateDockerNet creates a docker network or reusing if it exists
func (c *CLab) CreateDockerNet(ctx context.Context) (err error) {
nctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()
netCreateResponse, err = c.DockerClient.NetworkCreate(nctx, c.Config.Mgmt.Network, networkOptions)
if err != nil {
if strings.Contains(err.Error(), "already exists") {
log.Debugf("Container network %s already exists", c.Config.Mgmt.Network)
nctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()
netResource, err := c.DockerClient.NetworkInspect(nctx, c.Config.Mgmt.Network) //, types.NetworkInspectOptions{})
if err != nil {
return err
}
log.Debugf("container network: %+v", netResource)
if len(netResource.ID) < 12 {
return fmt.Errorf("could not get bridge ID")
}
bridgeName = "br-" + netResource.ID[:12]
} else {

// linux bridge name that is used by docker network
var bridgeName string

log.Debugf("Checking if docker network '%s' exists", c.Config.Mgmt.Network)
netResource, err := c.DockerClient.NetworkInspect(nctx, c.Config.Mgmt.Network)
switch {
case client.IsErrNetworkNotFound(err):
log.Debugf("Network '%s' does not exist", c.Config.Mgmt.Network)
log.Infof("Creating docker network: Name='%s', IPv4Subnet='%s', IPv6Subnet='%s'", c.Config.Mgmt.Network, c.Config.Mgmt.IPv4Subnet, c.Config.Mgmt.IPv6Subnet)

enableIPv6 := false
var ipamConfig []network.IPAMConfig
if c.Config.Mgmt.IPv4Subnet != "" {
ipamConfig = append(ipamConfig, network.IPAMConfig{
Subnet: c.Config.Mgmt.IPv4Subnet,
})
}
if c.Config.Mgmt.IPv6Subnet != "" {
ipamConfig = append(ipamConfig, network.IPAMConfig{
Subnet: c.Config.Mgmt.IPv6Subnet,
})
enableIPv6 = true
}

ipam := &network.IPAM{
Driver: "default",
Config: ipamConfig,
}

networkOptions := types.NetworkCreate{
CheckDuplicate: true,
Driver: "bridge",
EnableIPv6: enableIPv6,
IPAM: ipam,
Internal: false,
Attachable: false,
Labels: map[string]string{
"containerlab": "",
},
Options: map[string]string{
"com.docker.network.driver.mtu": c.Config.Mgmt.MTU,
},
}

netCreateResponse, err := c.DockerClient.NetworkCreate(nctx, c.Config.Mgmt.Network, networkOptions)
if err != nil {
return err
}
}
if len(bridgeName) == 0 {

if len(netCreateResponse.ID) < 12 {
return fmt.Errorf("could not get bridge ID")
}
bridgeName = "br-" + netCreateResponse.ID[:12]

case err == nil:
log.Debugf("network '%s' was found. Reusing it...", c.Config.Mgmt.Network)
if len(netResource.ID) < 12 {
return fmt.Errorf("could not get bridge ID")
}
bridgeName = "br-" + netResource.ID[:12]
default:
return err
}
log.Debugf("container network %s : bridge name: %s", c.Config.Mgmt.Network, bridgeName)

log.Debugf("Docker network '%s', bridge name '%s'", c.Config.Mgmt.Network, bridgeName)

log.Debug("Disable RPF check on the docker host")
err = setSysctl("net/ipv4/conf/all/rp_filter", 0)
Expand All @@ -101,7 +104,7 @@ func (c *CLab) CreateBridge(ctx context.Context) (err error) {
return fmt.Errorf("failed to disable RP filter on docker host for the 'default' scope: %v", err)
}

log.Debugf("Enable LLDP on the docker bridge %s", bridgeName)
log.Debugf("Enable LLDP on the linux bridge %s", bridgeName)
file := "/sys/class/net/" + bridgeName + "/bridge/group_fwd_mask"

err = ioutil.WriteFile(file, []byte(strconv.Itoa(16384)), 0640)
Expand Down
6 changes: 3 additions & 3 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ var deployCmd = &cobra.Command{
log.Debugf("root Cert: %s", string(rootCerts.Cert))
log.Debugf("root Key: %s", string(rootCerts.Key))

// create bridge
if err = c.CreateBridge(ctx); err != nil {
log.Error(err)
// create docker network or use existing one
if err = c.CreateDockerNet(ctx); err != nil {
return err
}

certTpl, err := template.ParseFiles(certCsrTemplate)
Expand Down
2 changes: 1 addition & 1 deletion cmd/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func destroyLab(ctx context.Context, c *clab.CLab) (err error) {
return fmt.Errorf("could not list containers: %v", err)
}

log.Infof("Destroying container lab: %s", topo)
log.Infof("Destroying container lab: %s", c.Config.Name)
wg := new(sync.WaitGroup)
wg.Add(len(containers))
for _, cont := range containers {
Expand Down

0 comments on commit fc1a50a

Please sign in to comment.