Skip to content

Commit

Permalink
Merge branch 'master' into config
Browse files Browse the repository at this point in the history
  • Loading branch information
hellt committed Jun 30, 2021
2 parents c3b34ff + 3db4ffb commit fa1d4e1
Show file tree
Hide file tree
Showing 15 changed files with 154 additions and 118 deletions.
2 changes: 1 addition & 1 deletion clab/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func (c *CLab) createNodeCfg(nodeName string, nodeDef *types.NodeDefinition, idx
log.Debugf("node config: %+v", nodeCfg)
var err error
// initialize config
nodeCfg.Config, err = c.Config.Topology.GetNodeConfig(nodeCfg.ShortName)
nodeCfg.StartupConfig, err = c.Config.Topology.GetNodeConfig(nodeCfg.ShortName)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/kinds/ceos.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ The generated config will be saved by the path `clab-<lab_name>/<node-name>/flas
cEOS Ma0 interface will be configured with a random MAC address with `00:1c:73` OUI part. Containerlab will also create a `system_mac_address` file in the node's lab directory with the value of a System MAC address. The System MAC address value is calculated as `Ma0-MAC-addr + 1`.

#### User defined config
It is possible to make ceos nodes to boot up with a user-defined config instead of a built-in one. With a [`config`](../nodes.md#config) property a user sets the path to the config file that will be mounted to a container and used as a startup config:
It is possible to make ceos nodes to boot up with a user-defined config instead of a built-in one. With a [`startup-config`](../nodes.md#startup-config) property a user sets the path to the config file that will be mounted to a container and used as a startup config:

```yaml
name: ceos_lab
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/kinds/crpd.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ topology:
The generated config will be saved by the path `clab-<lab_name>/<node-name>/config/juniper.conf`. Using the example topology presented above, the exact path to the config will be `clab-crpd/crpd/config/juniper.conf`.

#### User defined config
It is possible to make cRPD nodes to boot up with a user-defined config instead of a built-in one. With a [`config`](../nodes.md#config) property of the node/kind a user sets the path to the config file that will be mounted to a container:
It is possible to make cRPD nodes to boot up with a user-defined config instead of a built-in one. With a [`startup-config`](../nodes.md#startup-config) property of the node/kind a user sets the path to the config file that will be mounted to a container:

```yaml
name: crpd_lab
Expand Down
4 changes: 2 additions & 2 deletions docs/manual/kinds/srl.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ topology:

The generated config will be saved by the path `clab-<lab_name>/<node-name>/config/config.json`. Using the example topology presented above, the exact path to the config will be `clab-srl_lab/srl1/config/config.json`.

#### User defined config
It is possible to make SR Linux nodes to boot up with a user-defined config instead of a built-in one. With a [`config`](../nodes.md#config) property of the node/kind a user sets the path to the config file that will be mounted to a container:
#### User defined startup config
It is possible to make SR Linux nodes to boot up with a user-defined config instead of a built-in one. With a [`startup-config`](../nodes.md#startup-config) property of the node/kind a user sets the path to the config file that will be mounted to a container:

```yaml
name: srl_lab
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/kinds/vr-sros.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ type: "cpu=2 ram=4 slot=A chassis=ixr-r6 card=cpiom-ixr-r6 mda/1=m6-10g-sfp++4-2
vr-sros nodes come up with a basic "blank" configuration where only the card/mda are provisioned, as well as the management interfaces such as Netconf, SNMP, gNMI.

#### User defined config
It is possible to make SR OS nodes to boot up with a user-defined config instead of a built-in one. With a [`config`](../nodes.md#config) property of the node/kind a user sets the path to the config file that will be mounted to a container and used as a startup config:
It is possible to make SR OS nodes to boot up with a user-defined startup config instead of a built-in one. With a [`startup-config`](../nodes.md#startup-config) property of the node/kind a user sets the path to the config file that will be mounted to a container and used as a startup config:

```yaml
name: sros_lab
Expand Down
4 changes: 2 additions & 2 deletions docs/manual/nodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ docker tag srlinux:20.6.1-286 srlinux:latest
### license
Some containerized NOSes require a license to operate. With `license` property a user sets a path to a license file that a node will use. The license file will then be mounted to the container by the path that is defined by the `kind/type` of the node.

### config
For some kinds its possible to pass a path to a config file that a node will use on start instead of a bare config. Check documentation for a specific kind to see if `config` element is supported.
### startup-config
For some kinds it's possible to pass a path to a config file that a node will use on start instead of a bare config. Check documentation for a specific kind to see if `startup-config` element is supported.

### binds
In order to expose host files to the containerized nodes a user can leverage the bind mount capability.
Expand Down
23 changes: 21 additions & 2 deletions nodes/ceos/ceos.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
_ "embed"
"fmt"
"net"
"os"
"path"
"path/filepath"
"strings"
Expand Down Expand Up @@ -113,7 +114,21 @@ func createCEOSFiles(node *types.NodeConfig) error {
// generate config directory
utils.CreateDirectory(path.Join(node.LabDir, "flash"), 0777)
cfg := path.Join(node.LabDir, "flash", "startup-config")
node.ResConfig = cfg
node.ResStartupConfig = cfg

// use startup config file provided by a user
if node.StartupConfig != "" {
c, err := os.ReadFile(node.StartupConfig)
if err != nil {
return err
}
cfgTemplate = string(c)

err = node.GenerateConfig(node.ResStartupConfig, cfgTemplate)
if err != nil {
return err
}
}

// sysmac is a system mac that is +1 to Ma0 mac
m, err := net.ParseMAC(node.MacAddress)
Expand All @@ -126,8 +141,12 @@ func createCEOSFiles(node *types.NodeConfig) error {
}

func ceosPostDeploy(ctx context.Context, r runtime.ContainerRuntime, nodeCfg *types.NodeConfig) error {
// post deploy actions are not needed if a user specified startup config was provided
if nodeCfg.StartupConfig != "" {
return nil
}
// regenerate ceos config since it is now known which IP address docker assigned to this container
err := nodeCfg.GenerateConfig(nodeCfg.ResConfig, cfgTemplate)
err := nodeCfg.GenerateConfig(nodeCfg.ResStartupConfig, cfgTemplate)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions nodes/crpd/crpd.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ func (s *crpd) Init(cfg *types.NodeConfig, opts ...nodes.NodeOption) error {
for _, o := range opts {
o(s)
}
if s.cfg.Config == "" {
s.cfg.Config = nodes.DefaultConfigTemplates[s.cfg.Kind]
if s.cfg.StartupConfig == "" {
s.cfg.StartupConfig = nodes.DefaultConfigTemplates[s.cfg.Kind]
}

// mount config and log dirs
Expand Down
17 changes: 12 additions & 5 deletions nodes/srl/srl.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ func (s *srl) Init(cfg *types.NodeConfig, opts ...nodes.NodeOption) error {
for _, o := range opts {
o(s)
}
if s.cfg.Config == "" {
s.cfg.Config = nodes.DefaultConfigTemplates[s.cfg.Kind]
if s.cfg.StartupConfig == "" {
s.cfg.StartupConfig = nodes.DefaultConfigTemplates[s.cfg.Kind]
}
if s.cfg.License == "" {
return fmt.Errorf("no license found for node '%s' of kind '%s'", s.cfg.ShortName, s.cfg.Kind)
Expand Down Expand Up @@ -211,11 +211,18 @@ func createSRLFiles(nodeCfg *types.NodeConfig) error {
return err
}

// generate a config file
// if the node has a `config:` statement, the file specified in that section
// will be used as a template in nodeGenerateConfig()
// generate a startup config file
// if the node has a `startup-config:` statement, the file specified in that section
// will be used as a template in GenerateConfig()
utils.CreateDirectory(path.Join(nodeCfg.LabDir, "config"), 0777)
dst = path.Join(nodeCfg.LabDir, "config", "config.json")
if nodeCfg.StartupConfig != "" {
c, err := os.ReadFile(nodeCfg.StartupConfig)
if err != nil {
return err
}
cfgTemplate = string(c)
}
err = nodeCfg.GenerateConfig(dst, cfgTemplate)
if err != nil {
log.Errorf("node=%s, failed to generate config: %v", nodeCfg.ShortName, err)
Expand Down
25 changes: 16 additions & 9 deletions nodes/vr_sros/vr-sros.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package vr_sros
import (
"context"
"fmt"
"os"
"path"

log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -36,8 +37,8 @@ func (s *vrSROS) Init(cfg *types.NodeConfig, opts ...nodes.NodeOption) error {
for _, o := range opts {
o(s)
}
if s.cfg.Config == "" {
s.cfg.Config = nodes.DefaultConfigTemplates[s.cfg.Kind]
if s.cfg.StartupConfig == "" {
s.cfg.StartupConfig = nodes.DefaultConfigTemplates[s.cfg.Kind]
}
// vr-sros type sets the vrnetlab/sros variant (https://github.com/hellt/vrnetlab/sros)
if s.cfg.NodeType == "" {
Expand Down Expand Up @@ -112,15 +113,21 @@ func createVrSROSFiles(node *types.NodeConfig) error {
return fmt.Errorf("file copy [src %s -> dst %s] failed %v", src, dst, err)
}
log.Debugf("CopyFile src %s -> dst %s succeeded", src, dst)
}

if node.StartupConfig != "" {
cfg := path.Join(node.LabDir, "tftpboot", "config.txt")
if node.Config != "" {
err := node.GenerateConfig(cfg, nodes.DefaultConfigTemplates[node.Kind])
if err != nil {
log.Errorf("node=%s, failed to generate config: %v", node.ShortName, err)
}
} else {
log.Debugf("Config file exists for node %s", node.ShortName)

c, err := os.ReadFile(node.StartupConfig)
if err != nil {
return err
}

cfgTemplate := string(c)

err = node.GenerateConfig(cfg, cfgTemplate)
if err != nil {
log.Errorf("node=%s, failed to generate config: %v", node.ShortName, err)
}
}
return nil
Expand Down
6 changes: 3 additions & 3 deletions schemas/clab.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@
"description": "path to a license file",
"markdownDescription": "path to a [license](https://containerlab.srlinux.dev/manual/nodes/#license) file"
},
"config": {
"startup-config": {
"type": "string",
"description": "path to a config file (if supported by kind)",
"markdownDescription": "path to a [config file](https://containerlab.srlinux.dev/manual/nodes/#config) (if supported by kind)"
"description": "path to a startup config file (if supported by kind)",
"markdownDescription": "path to a [config file](https://containerlab.srlinux.dev/manual/nodes/#startup-config) (if supported by kind)"
},
"binds": {
"type": "array",
Expand Down
20 changes: 10 additions & 10 deletions types/node_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package types

// NodeDefinition represents a configuration a given node can have in the lab definition file
type NodeDefinition struct {
Kind string `yaml:"kind,omitempty"`
Group string `yaml:"group,omitempty"`
Type string `yaml:"type,omitempty"`
Config string `yaml:"config,omitempty"`
Image string `yaml:"image,omitempty"`
License string `yaml:"license,omitempty"`
Position string `yaml:"position,omitempty"`
Cmd string `yaml:"cmd,omitempty"`
Kind string `yaml:"kind,omitempty"`
Group string `yaml:"group,omitempty"`
Type string `yaml:"type,omitempty"`
StartupConfig string `yaml:"startup-config,omitempty"`
Image string `yaml:"image,omitempty"`
License string `yaml:"license,omitempty"`
Position string `yaml:"position,omitempty"`
Cmd string `yaml:"cmd,omitempty"`
// list of bind mount compatible strings
Binds []string `yaml:"binds,omitempty"`
// list of port bindings
Expand Down Expand Up @@ -51,11 +51,11 @@ func (n *NodeDefinition) GetType() string {
return n.Type
}

func (n *NodeDefinition) GetConfig() string {
func (n *NodeDefinition) GetStartupConfig() string {
if n == nil {
return ""
}
return n.Config
return n.StartupConfig
}

func (n *NodeDefinition) GetImage() string {
Expand Down
8 changes: 4 additions & 4 deletions types/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,12 @@ func (t *Topology) GetNodeConfig(name string) (string, error) {
var cfg string
if ndef, ok := t.Nodes[name]; ok {
var err error
cfg = ndef.GetConfig()
if t.GetKind(t.GetNodeKind(name)).GetConfig() != "" && cfg == "" {
cfg = t.GetKind(t.GetNodeKind(name)).GetConfig()
cfg = ndef.GetStartupConfig()
if t.GetKind(t.GetNodeKind(name)).GetStartupConfig() != "" && cfg == "" {
cfg = t.GetKind(t.GetNodeKind(name)).GetStartupConfig()
}
if cfg == "" {
cfg = t.GetDefaults().GetConfig()
cfg = t.GetDefaults().GetStartupConfig()
}
if cfg != "" {
cfg, err = resolvePath(cfg)
Expand Down
Loading

0 comments on commit fa1d4e1

Please sign in to comment.