Skip to content

Commit

Permalink
Merge branch 'srl-labs:master' into config
Browse files Browse the repository at this point in the history
  • Loading branch information
kellerza committed Jun 9, 2021
2 parents c5f771d + 34e8301 commit 4016ea4
Show file tree
Hide file tree
Showing 20 changed files with 178 additions and 24 deletions.
1 change: 1 addition & 0 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
filters: |
code:
- 'clab/**'
- 'runtime/**'
- 'cmd/**'
- 'tests/**'
- '.github/workflows/cicd.yml'
Expand Down
4 changes: 3 additions & 1 deletion clab/clab.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ func WithGracefulShutdown(gracefulShutdown bool) ClabOption {
// NewContainerLab function defines a new container lab
func NewContainerLab(opts ...ClabOption) *CLab {
c := &CLab{
Config: new(Config),
Config: &Config{
Mgmt: new(types.MgmtNet),
},
TopoFile: new(TopoFile),
m: new(sync.RWMutex),
Nodes: make(map[string]*types.Node),
Expand Down
25 changes: 20 additions & 5 deletions clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ var srlTypes = map[string]string{

// Config defines lab configuration as it is provided in the YAML file
type Config struct {
Name string `json:"name,omitempty"`
Mgmt types.MgmtNet `json:"mgmt,omitempty"`
Topology Topology `json:"topology,omitempty"`
ConfigPath string `yaml:"config_path,omitempty"`
Name string `json:"name,omitempty"`
Mgmt *types.MgmtNet `json:"mgmt,omitempty"`
Topology Topology `json:"topology,omitempty"`
ConfigPath string `yaml:"config_path,omitempty"`
}

// Topology represents a lab topology
Expand Down Expand Up @@ -585,6 +585,10 @@ func (c *CLab) CheckTopologyDefinition(ctx context.Context) error {
if err := c.VerifyImages(ctx); err != nil {
return err
}
if err := c.VerifyImages(ctx); err != nil { // skipcq: RVV-B0005
return err
}

return nil
}

Expand Down Expand Up @@ -649,6 +653,7 @@ func (c *CLab) VerifyImages(ctx context.Context) error {
}

// VerifyContainersUniqueness ensures that nodes defined in the topology do not have names of the existing containers
// additionally it checks that the lab name is unique and no containers are currently running with the same lab name label
func (c *CLab) VerifyContainersUniqueness(ctx context.Context) error {
nctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()
Expand All @@ -673,6 +678,16 @@ func (c *CLab) VerifyContainersUniqueness(ctx context.Context) error {
if len(dups) != 0 {
return fmt.Errorf("containers %q already exist. Add '--reconfigure' flag to the deploy command to first remove the containers and then deploy the lab", dups)
}

// check that none of the existing containers has a label that matches
// the lab name of a currently deploying lab
// this ensures lab uniqueness
for _, cnt := range containers {
if cnt.Labels["containerlab"] == c.Config.Name {
return fmt.Errorf("the '%s' lab has already been deployed. Destroy the lab before deploying a lab with the same name", c.Config.Name)
}
}

return err
}

Expand Down Expand Up @@ -846,7 +861,7 @@ func (c *CLab) CheckResources() error {
}
freeMemG := sysMemory("free") / 1024 / 1024 / 1024
if freeMemG < 1 {
log.Warnf("it appears that container host has low memory available: ~%dGi. This might lead to runtimer errors. Consider freeing up more memory.", freeMemG)
log.Warnf("it appears that container host has low memory available: ~%dGi. This might lead to runtime errors. Consider freeing up more memory.", freeMemG)
}
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/srl-labs/containerlab/clab"
"github.com/srl-labs/containerlab/types"
"gopkg.in/yaml.v2"
)

Expand Down Expand Up @@ -129,6 +130,7 @@ func generateTopologyConfig(name, network, ipv4range, ipv6range string, images m
numStages := len(nodes)
config := &clab.Config{
Name: name,
Mgmt: new(types.MgmtNet),
Topology: clab.Topology{
Kinds: make(map[string]clab.NodeConfig),
Nodes: make(map[string]clab.NodeConfig),
Expand Down
1 change: 1 addition & 0 deletions cmd/verUpgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var upgradeCmd = &cobra.Command{
_ = downloadFile(downloadURL, f)

c := exec.Command("bash", f.Name())
// c.Stdin = os.Stdin
c.Stdout = os.Stdout
c.Stderr = os.Stderr
err = c.Run()
Expand Down
9 changes: 5 additions & 4 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ var versionCmd = &cobra.Command{

Run: func(cmd *cobra.Command, args []string) {
fmt.Println(slug)
fmt.Printf("version: %s\n", version)
fmt.Printf(" commit: %s\n", commit)
fmt.Printf(" date: %s\n", date)
fmt.Printf(" source: %s\n", repoUrl)
fmt.Printf(" version: %s\n", version)
fmt.Printf(" commit: %s\n", commit)
fmt.Printf(" date: %s\n", date)
fmt.Printf(" source: %s\n", repoUrl)
fmt.Printf(" rel. notes: https://containerlab.srlinux.dev/rn/%s\n", version)
},
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/vxlan.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func init() {
vxlanCmd.AddCommand(vxlanDeleteCmd)

vxlanCreateCmd.Flags().IntVarP(&vxlanID, "id", "i", 10, "VxLAN ID (VNI)")
vxlanCreateCmd.Flags().StringVarP(&vxlanRemote, "remote", "r", "", "address of the remote VTEP")
vxlanCreateCmd.Flags().StringVarP(&vxlanRemote, "remote", "", "", "address of the remote VTEP")
vxlanCreateCmd.Flags().StringVarP(&parentDev, "dev", "", "", "parent (source) interface name for VxLAN")
vxlanCreateCmd.Flags().StringVarP(&cntLink, "link", "l", "", "link to which 'attach' vxlan tunnel with tc redirect")
vxlanCreateCmd.Flags().IntVarP(&vxlanMTU, "mtu", "m", 1554, "VxLAN MTU")
Expand Down
4 changes: 2 additions & 2 deletions docs/cmd/tools/vxlan/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ VxLAN interface name will be a catenation of a prefix `vx-` and the interface na
### Flags

#### remote
VxLAN tunnels set up with this command are unidirectional in nature. To set the remote endpoint address the `--remote | -r` flag should be used.
VxLAN tunnels set up with this command are unidirectional in nature. To set the remote endpoint address the `--remote` flag should be used.

#### id
VNI that the VxLAN tunnel will use is set with `--id | -i` flag. Defaults to `10`.
Expand Down Expand Up @@ -46,7 +46,7 @@ With `--mtu | -m` flag it is possible to set VxLAN MTU. Max MTU is automatically
link/ether fa:4c:16:11:11:05 brd ff:ff:ff:ff:ff:ff link-netns clab-vx-srl1

# create a vxlan tunnel to a remote vtep 10.0.0.20 with VNI 10 and redirect traffic to srl_e1-1 interface
❯ clab tools vxlan create -r 10.0.0.20 -l srl_e1-1 --id 10
❯ clab tools vxlan create --remote 10.0.0.20 -l srl_e1-1 --id 10
INFO[0000] Adding VxLAN link vx-srl_e1-1 under ens3 to remote address 10.0.0.20 with VNI 10
INFO[0000] configuring ingress mirroring with tc in the direction of vx-srl_e1-1 -> srl_e1-1
INFO[0000] configuring ingress mirroring with tc in the direction of srl_e1-1 -> vx-srl_e1-1
Expand Down
2 changes: 2 additions & 0 deletions docs/htmltest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ DirectoryPath: ./site
IgnoreURLs:
- fonts.gstatic.com
- img.shields.io
- www.reddit.com/r/bashonubuntuonwindows/comments/ldbyxa/what_is_the_current_state_of_kvm_acceleration_on/ # sometimes timeouts for unknown reason
- goreleaser.com # doesn't support `range 0` GETs which htmltest uses
IgnoreDirectoryMissingTrailingSlash: true
IgnoreAltMissing: true
IgnoreSSLVerify: true
Expand Down
12 changes: 12 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ This command will fetch the installation script and will upgrade the tool to its

or leverage `apt`/`yum` utilities if containerlab repo was added as explained in the [Package managers](#package-managers) section.

### From source
To build containerlab from source:

=== "with go build"
To build containerlab from source, clone the repository and issue `go build` at its root.
=== "with goreleaser"
When we release containerlab we use [goreleaser](https://goreleaser.com/) project to build binaries for all supported platforms as well as the deb/rpm packages.
Users can install `goreleaser` and do the same locally by issuing the following command:
```
goreleaser --snapshot --skip-publish --rm-dist
```

[^1]: only available if installed from packages
[^2]: Most containerized NOS will require >1 vCPU. RAM size depends on the lab size. Architecture: AMD64.
[^3]: No need to uninstall Docker Desktop, just make sure that it is not integrated with WSL2 machine that you intend to use with containerlab. Moreover, you can make it even work with Docker Desktop with a [few additional steps](https://twitter.com/networkop1/status/1380976461641834500/photo/1), but installing docker-ce into the WSL maybe more intuitive.
3 changes: 3 additions & 0 deletions docs/manual/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ PING 172.20.20.3 (172.20.20.3) 56(84) bytes of data.
!!!note
If you run multiple labs without changing the default management settings, the containers of those labs will end up connecting to the same management network with their management interface.

### host mode networking
In addition to the bridge-based management network containerlab supports launching nodes in [host networking mode](https://docs.docker.com/network/host/). In this mode containers are attached to the host network namespace. Host mode is enabled with [network-mode](nodes.md#network-mode) node setting.

### configuring management network
Most of the time there is no need to change the defaults for management network configuration, but sometimes it is needed. For example, it might be that the default network ranges are overlapping with existing addressing scheme on the lab host or it might be desirable to have predefined management IP addresses.

Expand Down
5 changes: 5 additions & 0 deletions docs/rn/0.14.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Release 0.14.2
:material-calendar: 2021-05-27

## fix additional interfaces to management network
This patch release fixes issues with containerlab failing to add additional data interfaces to management network as described [here](../manual/network.md#additional-connections-to-management-network).
9 changes: 9 additions & 0 deletions docs/rn/0.14.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Release 0.14.3
:material-calendar: 2021-05-28


## Fixes and improvements
- fixed missing IPv4/6 information in `containerlab inspect --all` output
- prevented deployment of the lab if the same-named lab has already been deployed
- install script now checks if the released version set by the user actually exists

9 changes: 9 additions & 0 deletions docs/rn/0.14.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Release 0.14.34
:material-calendar: 2021-06-06


## Fixes and improvements
- [fixed](https://github.com/srl-labs/containerlab/pull/440) generate command
- added "Y/n" prompt when doing `containerlab version upgrade`.
- version command will return a link to the relevant release notes

25 changes: 23 additions & 2 deletions get.sh
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ setDesiredVersion() {
else
TAG=$DESIRED_VERSION
TAG_WO_VER=$(echo "${TAG}" | cut -c 2-)

if type "curl" &>/dev/null; then
if ! curl -s -o /dev/null --fail https://api.github.com/repos/$REPO_NAME/releases/tags/$DESIRED_VERSION; then
echo "release $DESIRED_VERSION not found"
exit 1
fi
elif type "wget" &>/dev/null; then
if ! wget -q https://api.github.com/repos/$REPO_NAME/releases/tags/$DESIRED_VERSION; then
echo "release $DESIRED_VERSION not found"
exit 1
fi
fi
fi
}

Expand All @@ -110,8 +122,17 @@ checkInstalledVersion() {
echo "${BINARY_NAME} is already at ${DESIRED_VERSION:-latest ($version)}" version
return 0
else
echo "${BINARY_NAME} ${TAG_WO_VER} is available. Changing from version ${version}."
return 1
echo "A newer ${BINARY_NAME} ${TAG_WO_VER} is available. Release notes: https://containerlab.srlinux.dev/rn/${TAG_WO_VER}"
echo "You are running containerlab $version version"
UPGR_NEEDED="Y"
# check if stdin is open (i.e. capable of getting users input)
if [ -t 0 ]; then
read -e -p "Proceed with upgrade? [Y/n]: " -i "Y" UPGR_NEEDED
fi
if [ "$UPGR_NEEDED" == "Y" ]; then
return 1
fi
return 0
fi
else
return 1
Expand Down
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ nav:
- BGP VPLS between Nokia and Juniper: lab-examples/bgp-vpls-nok-jun.md
- Multi-node labs: lab-examples/multinode.md
- Release notes:
- 0.14.4: rn/0.14.4.md
- 0.14.3: rn/0.14.3.md
- 0.14.2: rn/0.14.2.md
- 0.14.1: rn/0.14.1.md
- 0.14.0: rn/0.14.0.md
- 0.13.0: rn/0.13.0.md
Expand Down
40 changes: 32 additions & 8 deletions runtime/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const sysctlBase = "/proc/sys"
type DockerRuntime struct {
Client *dockerC.Client
timeout time.Duration
Mgmt types.MgmtNet
Mgmt *types.MgmtNet
debug bool
gracefulShutdown bool
}
Expand All @@ -41,14 +41,15 @@ func NewDockerRuntime(d bool, dur time.Duration, gracefulShutdown bool) *DockerR

return &DockerRuntime{
Client: c,
Mgmt: new(types.MgmtNet),
// TODO: undo this hard-coding
timeout: dur,
debug: d,
gracefulShutdown: gracefulShutdown,
}
}

func (c *DockerRuntime) SetMgmtNet(n types.MgmtNet) {
func (c *DockerRuntime) SetMgmtNet(n *types.MgmtNet) {
c.Mgmt = n
}

Expand Down Expand Up @@ -345,28 +346,41 @@ func (c *DockerRuntime) StartContainer(ctx context.Context, id string) error {

// ListContainers lists all containers with labels []string
func (c *DockerRuntime) ListContainers(ctx context.Context, labels []string) ([]types.GenericContainer, error) {
ctx, cancel := context.WithTimeout(ctx, c.timeout)
nctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()
filter := filters.NewArgs()
for _, l := range labels {
filter.Add("label", l)
}
ctrs, err := c.Client.ContainerList(ctx, dockerTypes.ContainerListOptions{
ctrs, err := c.Client.ContainerList(nctx, dockerTypes.ContainerListOptions{
All: true,
Filters: filter,
})
if err != nil {
return nil, err
}
var nr []dockerTypes.NetworkResource
if c.Mgmt.Network == "" {
netFilter := filters.NewArgs()
netFilter.Add("label", "containerlab")
nctx, cancel := context.WithTimeout(ctx, c.timeout)
defer cancel()

return c.produceGenericContainerList(ctrs)
nr, err = c.Client.NetworkList(nctx, dockerTypes.NetworkListOptions{
Filters: netFilter,
})
if err != nil {
return nil, err
}
}
return c.produceGenericContainerList(ctrs, nr)
}

// Transform docker-specific to generic container format
func (c *DockerRuntime) produceGenericContainerList(input []dockerTypes.Container) ([]types.GenericContainer, error) {
func (c *DockerRuntime) produceGenericContainerList(inputContainers []dockerTypes.Container, inputNetworkRessources []dockerTypes.NetworkResource) ([]types.GenericContainer, error) {
var result []types.GenericContainer

for _, i := range input {
for _, i := range inputContainers {
ctr := types.GenericContainer{
Names: i.Names,
ID: i.ID,
Expand All @@ -378,7 +392,17 @@ func (c *DockerRuntime) produceGenericContainerList(input []dockerTypes.Containe
Set: false,
},
}
if ifcfg, ok := i.NetworkSettings.Networks[c.Mgmt.Network]; ok {
bridgeName := c.Mgmt.Network
// if bridgeName is "", try to find a network created by clab that the container is connected to
if bridgeName == "" && inputNetworkRessources != nil {
for _, nr := range inputNetworkRessources {
if _, ok := i.NetworkSettings.Networks[nr.Name]; ok {
bridgeName = nr.Name
break
}
}
}
if ifcfg, ok := i.NetworkSettings.Networks[bridgeName]; ok {
ctr.NetworkSettings.IPv4addr = ifcfg.IPAddress
ctr.NetworkSettings.IPv4pLen = ifcfg.IPPrefixLen
ctr.NetworkSettings.IPv6addr = ifcfg.GlobalIPv6Address
Expand Down
2 changes: 1 addition & 1 deletion runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const (

type ContainerRuntime interface {
// Set the network management details (generated by the config.go)
SetMgmtNet(types.MgmtNet)
SetMgmtNet(*types.MgmtNet)
// Create container (bridge) network
CreateNet(context.Context) error
// Delete container (bridge) network
Expand Down
17 changes: 17 additions & 0 deletions tests/01-smoke/01-basic-flow.robot
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
*** Settings ***
Library OperatingSystem
Library String
Suite Teardown Run sudo containerlab destroy -t ${CURDIR}/01-linux-nodes.clab.yml --cleanup

*** Variables ***
Expand Down Expand Up @@ -43,6 +44,22 @@ Verify links in node l2
Should Be Equal As Integers ${rc} 0
Should Contain ${output} state UP

Ensure "inspect all" outputs IP addresses
${rc} ${output} = Run And Return Rc And Output
... sudo containerlab inspect --all
Log ${output}
Should Be Equal As Integers ${rc} 0
${line} = String.Get Line ${output} -2
Log ${line}
@{data} = Split String ${line} |
Log ${data}
# verify ipv4 address
${ipv4} = String.Strip String ${data}[10]
Should Match Regexp ${ipv4} ^[\\d\\.]+/\\d{1,2}$
# verify ipv6 address
${ipv6} = String.Strip String ${data}[11]
Should Match Regexp ${ipv6} ^[\\d:]+/\\d{1,2}$

Destroy ${lab-name} lab
${rc} ${output} = Run And Return Rc And Output
... sudo containerlab destroy -t ${CURDIR}/01-linux-nodes.clab.yml --cleanup
Expand Down
Loading

0 comments on commit 4016ea4

Please sign in to comment.