Skip to content

Commit

Permalink
Merge branch 'master' into rn-0.15.0
Browse files Browse the repository at this point in the history
  • Loading branch information
hellt committed Jul 16, 2021
2 parents 734f9a5 + f9490a2 commit 620375e
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 83 deletions.
150 changes: 97 additions & 53 deletions clab/clab.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,45 +151,68 @@ func (c *CLab) GlobalRuntime() runtime.ContainerRuntime {
return c.Runtimes[c.globalRuntime]
}

func (c *CLab) CreateNodes(ctx context.Context, workers uint) {
func (c *CLab) CreateNodes(ctx context.Context, maxWorkers uint, serialNodes map[string]struct{}) {

wg := new(sync.WaitGroup)
wg.Add(int(workers))
nodesChan := make(chan nodes.Node)
// start workers
for i := uint(0); i < workers; i++ {
go func(i uint) {
defer wg.Done()
for {
select {
case node, ok := <-nodesChan:
if node == nil || !ok {
log.Debugf("Worker %d terminating...", i)
return
}
log.Debugf("Worker %d received node: %+v", i, node.Config())
// PreDeploy
err := node.PreDeploy(c.Config.Name, c.Dir.LabCA, c.Dir.LabCARoot)
if err != nil {
log.Errorf("failed pre-deploy phase for node %q: %v", node.Config().ShortName, err)
continue
}
// Deploy
err = node.Deploy(ctx)
if err != nil {
log.Errorf("failed deploy phase for node %q: %v", node.Config().ShortName, err)
continue
}
case <-ctx.Done():

concurrentChan := make(chan nodes.Node)
serialChan := make(chan nodes.Node)

workerFunc := func(i uint, input chan nodes.Node, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case node, ok := <-input:
if node == nil || !ok {
log.Debugf("Worker %d terminating...", i)
return
}
log.Debugf("Worker %d received node: %+v", i, node.Config())
// PreDeploy
err := node.PreDeploy(c.Config.Name, c.Dir.LabCA, c.Dir.LabCARoot)
if err != nil {
log.Errorf("failed pre-deploy phase for node %q: %v", node.Config().ShortName, err)
continue
}
// Deploy
err = node.Deploy(ctx)
if err != nil {
log.Errorf("failed deploy phase for node %q: %v", node.Config().ShortName, err)
continue
}
case <-ctx.Done():
return
}
}(i)
}
}

// start concurrent workers
wg.Add(int(maxWorkers))
// it's safe to not check if all nodes are serial because in that case
// maxWorkers will be 0
for i := uint(0); i < maxWorkers; i++ {
go workerFunc(i, concurrentChan, wg)
}

// start the serial worker
if len(serialNodes) > 0 {
wg.Add(1)
go workerFunc(maxWorkers, serialChan, wg)
}

// send nodes to workers
for _, n := range c.Nodes {
nodesChan <- n
if _, ok := serialNodes[n.Config().LongName]; ok {
serialChan <- n
continue
}
concurrentChan <- n
}

// close channel to terminate the workers
close(nodesChan)
close(concurrentChan)
close(serialChan)

// wait for all workers to finish
wg.Wait()
}
Expand Down Expand Up @@ -248,35 +271,56 @@ func (c *CLab) CreateLinks(ctx context.Context, workers uint, postdeploy bool) {
wg.Wait()
}

func (c *CLab) DeleteNodes(ctx context.Context, workers uint, deleteCandidates map[string]nodes.Node) {
func (c *CLab) DeleteNodes(ctx context.Context, workers uint, deleteCandidates map[string]nodes.Node, serialNodes map[string]struct{}) {

wg := new(sync.WaitGroup)

nodeChan := make(chan nodes.Node)
wg.Add(int(workers))
for i := uint(0); i < workers; i++ {
go func(i uint) {
defer wg.Done()
for {
select {
case n := <-nodeChan:
if n == nil {
log.Debugf("Worker %d terminating...", i)
return
}
err := n.Delete(ctx)
if err != nil {
log.Errorf("could not remove container %q: %v", n.Config().LongName, err)
}
case <-ctx.Done():
concurrentChan := make(chan nodes.Node)
serialChan := make(chan nodes.Node)

workerFunc := func(i uint, input chan nodes.Node, wg *sync.WaitGroup) {
defer wg.Done()
for {
select {
case n := <-input:
if n == nil {
log.Debugf("Worker %d terminating...", i)
return
}
err := n.Delete(ctx)
if err != nil {
log.Errorf("could not remove container %q: %v", n.Config().LongName, err)
}
case <-ctx.Done():
return
}
}(i)
}
}
for _, n := range deleteCandidates {
nodeChan <- n

// start concurrent workers
wg.Add(int(workers))
for i := uint(0); i < workers; i++ {
go workerFunc(i, concurrentChan, wg)
}

// start the serial worker
if len(serialNodes) > 0 {
wg.Add(1)
go workerFunc(workers, serialChan, wg)
}
close(nodeChan)

// send nodes to workers
for _, n := range c.Nodes {
if _, ok := serialNodes[n.Config().LongName]; ok {
serialChan <- n
continue
}
concurrentChan <- n
}

// close channel to terminate the workers
close(concurrentChan)
close(serialChan)

wg.Wait()

Expand Down
20 changes: 13 additions & 7 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,17 @@ var deployCmd = &cobra.Command{
linkWorkers = maxWorkers
}

// Serializing ignite workers due to busy device error
if _, ok := c.Runtimes[runtime.IgniteRuntime]; ok {
nodeWorkers = 1
// a set of workers that do not support concurrency
serialNodes := make(map[string]struct{})
for _, n := range c.Nodes {
if n.GetRuntime().GetName() == runtime.IgniteRuntime {
serialNodes[n.Config().LongName] = struct{}{}
// decreasing the num of nodeworkers as they are used for concurrent nodes
nodeWorkers = nodeWorkers - 1
}
}

c.CreateNodes(ctx, nodeWorkers)
c.CreateNodes(ctx, nodeWorkers, serialNodes)
c.CreateLinks(ctx, linkWorkers, false)
log.Debug("containers created, retrieving state and IP addresses...")

Expand All @@ -142,16 +147,17 @@ var deployCmd = &cobra.Command{
return err
}

var wg sync.WaitGroup
wg := &sync.WaitGroup{}
wg.Add(len(c.Nodes))

for _, node := range c.Nodes {
go func(node nodes.Node) {
go func(node nodes.Node, wg *sync.WaitGroup) {
defer wg.Done()
err := node.PostDeploy(ctx, c.Nodes)
if err != nil {
log.Errorf("failed to run postdeploy task for node %s: %v", node.Config().ShortName, err)
}
}(node)
}(node, wg)
}
wg.Wait()

Expand Down
12 changes: 11 additions & 1 deletion cmd/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,23 @@ func destroyLab(ctx context.Context, c *clab.CLab) (err error) {
maxWorkers = uint(len(c.Nodes))
}

// a set of workers that do not support concurrency
serialNodes := make(map[string]struct{})
for _, n := range c.Nodes {
if n.GetRuntime().GetName() == runtime.IgniteRuntime {
serialNodes[n.Config().LongName] = struct{}{}
// decreasing the num of maxWorkers as they are used for concurrent nodes
maxWorkers = maxWorkers - 1
}
}

// Serializing ignite workers due to busy device error
if _, ok := c.Runtimes[runtime.IgniteRuntime]; ok {
maxWorkers = 1
}

log.Infof("Destroying lab: %s", c.Config.Name)
c.DeleteNodes(ctx, maxWorkers, c.Nodes)
c.DeleteNodes(ctx, maxWorkers, c.Nodes, serialNodes)

// remove the lab directories
if cleanup {
Expand Down
9 changes: 9 additions & 0 deletions docs/cmd/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ Refer to the [configuration artifacts](../manual/conf-artifacts.md) page to get
#### max-workers
With `--max-workers` flag it is possible to limit the amout of concurrent workers that create containers or wire virtual links. By default the number of workers equals the number of nodes/links to create.

#### runtime
Containerlab nodes can be started by different runtimes, with `docker` being the default one. Besides `docker`, containerlab has experimental support for `containerd` and `ignite` runtimes.

A global runtime can be selected with a global `--runtime | -r` flag that will select a runtime to use. The supported value are:

* `docker` - default
* `containerd`
* `ignite`

### Examples

```bash
Expand Down
10 changes: 5 additions & 5 deletions docs/lab-examples/cvx03.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
| **Description** | Cumulus Linux Test Drive |
| **Components** | [Cumulus Linux][cvx] |
| **Resource requirements**[^1] | :fontawesome-solid-microchip: 2 <br/>:fontawesome-solid-memory: 2 GB |
| **Topology file** | [lab-start.yml][topofile] <br/>[lab-final.yml][finalfile] |
| **Topology file** | [lab-start.clab.yml][topofile] <br/>[lab-final.clab.yml][finalfile] |
| **Name** | cvx03 |
| **Version information**[^2] | `cvx:4.3.0` `docker-ce:19.03.13` |

Expand All @@ -19,13 +19,13 @@ This is a "Cumulus Test Drive" topology designed to provide an overview of NVIDI
2. BGP Unnumbered (Lab3) -- learn how to configure BGP unnumbered between leaf and spine switches and advertise locally connected interfaces.

!!!note
Everything from Lab1 is already pre-configured when the topology is created with [lab-start.yml][topofile].
Everything from Lab1 is already pre-configured when the topology is created with [lab-start.clab.yml][topofile].

Additionally, the lab directory contains a [lab-final.yml][finalfile] which will load final configurations as they appear at the end of Lab3.
Additionally, the lab directory contains a [lab-final.clab.yml][finalfile] which will load final configurations as they appear at the end of Lab3.

[cvx]: https://www.nvidia.com/en-gb/networking/ethernet-switching/cumulus-vx/
[topofile]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx03/lab-start.yml
[finalfile]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx03/lab-final.yml
[topofile]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx03/lab-start.clab.yml
[finalfile]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx03/lab-final.clab.yml

[^1]: Resource requirements are provisional. Consult with the installation guides for additional information.
[^2]: The lab has been validated using these versions of the required tools/components. Using versions other than stated might lead to a non-operational setup process.
Expand Down
11 changes: 4 additions & 7 deletions docs/lab-examples/cvx04.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
| **Description** | Cumulus In The Cloud |
| **Components** | [Cumulus Linux][cvx] |
| **Resource requirements**[^1] | :fontawesome-solid-microchip: 2 <br/>:fontawesome-solid-memory: 4 GB |
| **Topology file** | [symm-mh.yml][topo-mh] <br/>[symm-mlag.yml][topo-mlag] |
| **Topology file** | [symm-mh.clab.yml][topo-mh] <br/>[symm-mlag.clab.yml][topo-mlag] |
| **Name** | cvx04 |
| **Version information**[^2] | `cvx:4.3.0` `docker-ce:19.03.13` |

Expand All @@ -21,7 +21,7 @@ This is a "Cumulus In The Cloud" topology designed to demonstrate some of the ad

## Instructions

Each configuration option is provided in its own configuration file -- [`symm-mh.yml`][topo-mh] or [`symm-mlag.yml`][topo-mlag]. See [instructions](/lab-examples/lab-examples/#how-to-deploy-a-lab-from-the-lab-catalog) for how to deploy a topology.
Each configuration option is provided in its own configuration file -- [`symm-mh.clab.yml`][topo-mh] or [`symm-mlag.clab.yml`][topo-mlag]. See [instructions](/lab-examples/lab-examples/#how-to-deploy-a-lab-from-the-lab-catalog) for how to deploy a topology.

Once up, each node can be accessed via ssh using its hostname (automatically populated in your `/etc/hosts` file) and the default credentials `root/root`:

Expand All @@ -34,13 +34,10 @@ Last login: Fri Jul 9 13:35:48 2021 from 192.168.223.1
root@94992c82719f1172:mgmt:~#
```

!!!note
Due to the different boot order inside a container, BGPd may come up stuck waiting for IPv6 LLA of the peer. This issue only appears on the initial boot and can be fixed with the `vtysh -c 'clear ip bgp *` command.


[cvx]: https://www.nvidia.com/en-gb/networking/ethernet-switching/cumulus-vx/
[topo-mh]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx04/symm-mh.yml
[topo-mlag]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx04/symm-mlag.yml
[topo-mh]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx04/symm-mh.clab.yml
[topo-mlag]: https://github.com/srl-labs/containerlab/tree/master/lab-examples/cvx04/symm-mlag.clab.yml

[^1]: Resource requirements are provisional. Consult with the installation guides for additional information.
[^2]: The lab has been validated using these versions of the required tools/components. Using versions other than stated might lead to a non-operational setup process.
Expand Down
6 changes: 3 additions & 3 deletions docs/manual/kinds/cvx.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CVX nodes launched with containerlab comes up with:
CVX supports two modes of operation:

* Using Firecracker micro-VMs -- this mode runs Cumulus VX inside a micro-VM on top of the native Cumulus kernel. This is the default way of running CVX nodes.
* Using only the container runtime -- this mode runs Cumulus VX container image directly inside the container runtime (e.g. Docker). Due to the lack of Cumulus VX kernel modules, some features are not supported, most notable one being MLAG. In order to use this mode add `runtime: docker` under the cvx node definition (see also [this example](https://github.com/srl-labs/containerlab/blob/master/lab-examples/cvx02/topo.yml)).
* Using only the container runtime -- this mode runs Cumulus VX container image directly inside the container runtime (e.g. Docker). Due to the lack of Cumulus VX kernel modules, some features are not supported, most notable one being MLAG. In order to use this mode add `runtime: docker` under the cvx node definition (see also [this example](https://github.com/srl-labs/containerlab/blob/master/lab-examples/cvx02/topo.clab.yml)).


## Managing cvx nodes
Expand Down Expand Up @@ -63,8 +63,8 @@ This will be addressed in the future releases.
## Lab examples
The following labs feature CVX node:

- [Cumulus Linux Test Drive](https://github.com/srl-labs/containerlab/blob/master/lab-examples/cvx03/lab-start.yml)
- [Cumulus and FRR](https://github.com/srl-labs/containerlab/blob/master/lab-examples/cvx01/topo.yml)
- [Cumulus Linux Test Drive](https://github.com/srl-labs/containerlab/blob/master/lab-examples/cvx03/lab-start.clab.yml)
- [Cumulus and FRR](https://github.com/srl-labs/containerlab/blob/master/lab-examples/cvx01/topo.clab.yml)


## Known issues or limitations
Expand Down
21 changes: 20 additions & 1 deletion docs/manual/nodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,23 @@ my-node:
network-mode: host
```

The `network-mode` configuration option set to `host` will launch the node in the [host networking mode](https://docs.docker.com/network/host/).
The `network-mode` configuration option set to `host` will launch the node in the [host networking mode](https://docs.docker.com/network/host/).

### runtime
By default containerlab nodes will be started by `docker` container runtime. Besides that, containerlab has experimental support for `containerd` and `ignite` runtimes.

It is possible to specify a global runtime with a global `--runtime` flag, or set the runtime on a per-node basis:

Options for the runtime parameter are:
- `docker`
- `containerd`
- `ignite`

The default runtime can also be influenced via the `CLAB_RUNTIME` environment variable, which takes the same values as mentioned above.

```yaml
# example node definition with per-node runtime definition
my-node:
image: alpine:3
runtime: containerd
```
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 620375e

Please sign in to comment.