Skip to content

Commit

Permalink
Revert "New link structs from raw (#1475)"
Browse files Browse the repository at this point in the history
This reverts commit 0b023dc.
  • Loading branch information
hellt committed Aug 19, 2023
1 parent dd86c24 commit 3fbb328
Show file tree
Hide file tree
Showing 80 changed files with 933 additions and 1,909 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
${{ runner.os }}-go-
- name: Build containerlab
run: make build-with-podman-debug BINARY=containerlab
run: make build-with-podman BINARY=containerlab
# store clab binary as artifact
- uses: actions/upload-artifact@v3
with:
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ MOCKDIR = ./mocks
.PHONY: mocks-gen
mocks-gen: mocks-rm ## Generate mocks for all the defined interfaces.
go install github.com/golang/mock/mockgen@v1.6.0
mockgen -package=mocknodes -source=nodes/node.go -destination=$(MOCKDIR)/mocknodes/node.go
mockgen -package=mocks -source=nodes/node.go -destination=$(MOCKDIR)/node.go
mockgen -package=mocks -source=clab/dependency_manager/dependency_manager.go -destination=$(MOCKDIR)/dependency_manager.go
mockgen -package=mockruntime -source=runtime/runtime.go -destination=$(MOCKDIR)/mockruntime/runtime.go
mockgen -package=mocknodes -source=nodes/default_node.go -destination=$(MOCKDIR)/mocknodes/default_node.go
mockgen -package=mocks -source=runtime/runtime.go -destination=$(MOCKDIR)/runtime.go
mockgen -package=mocks -source=nodes/default_node.go -destination=$(MOCKDIR)/default_node.go
mockgen -package=mocks -source=clab/exec/exec.go -destination=$(MOCKDIR)/exec.go

.PHONY: mocks-rm
Expand Down
12 changes: 6 additions & 6 deletions border0_api/border0_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

"github.com/golang/mock/gomock"
"github.com/h2non/gock"
"github.com/srl-labs/containerlab/mocks/mocknodes"
"github.com/srl-labs/containerlab/mocks"
"github.com/srl-labs/containerlab/nodes"
"github.com/srl-labs/containerlab/types"
)
Expand Down Expand Up @@ -211,7 +211,7 @@ func Test_createBorder0Config(t *testing.T) {
// getNodeMap return a map of nodes for testing purpose.
func getNodeMap(mockCtrl *gomock.Controller) map[string]nodes.Node {
// instantiate Mock Node 1
mockNode1 := mocknodes.NewMockNode(mockCtrl)
mockNode1 := mocks.NewMockNode(mockCtrl)
mockNode1.EXPECT().Config().Return(
&types.NodeConfig{
Image: "alpine:3",
Expand All @@ -221,7 +221,7 @@ func getNodeMap(mockCtrl *gomock.Controller) map[string]nodes.Node {
).AnyTimes()

// instantiate Mock Node 2
mockNode2 := mocknodes.NewMockNode(mockCtrl)
mockNode2 := mocks.NewMockNode(mockCtrl)
mockNode2.EXPECT().Config().Return(
&types.NodeConfig{
Image: "alpine:3",
Expand All @@ -236,7 +236,7 @@ func getNodeMap(mockCtrl *gomock.Controller) map[string]nodes.Node {
).AnyTimes()

// instantiate Mock Node 3
mockNode3 := mocknodes.NewMockNode(mockCtrl)
mockNode3 := mocks.NewMockNode(mockCtrl)
mockNode3.EXPECT().Config().Return(
&types.NodeConfig{
Image: "alpine:3",
Expand All @@ -248,7 +248,7 @@ func getNodeMap(mockCtrl *gomock.Controller) map[string]nodes.Node {
).AnyTimes()

// instantiate Mock Node 4
mockNode4 := mocknodes.NewMockNode(mockCtrl)
mockNode4 := mocks.NewMockNode(mockCtrl)
mockNode4.EXPECT().Config().Return(
&types.NodeConfig{
Image: "alpine:3",
Expand All @@ -259,7 +259,7 @@ func getNodeMap(mockCtrl *gomock.Controller) map[string]nodes.Node {
).AnyTimes()

// instantiate Mock Node 5
mockNode5 := mocknodes.NewMockNode(mockCtrl)
mockNode5 := mocks.NewMockNode(mockCtrl)
mockNode5.EXPECT().Config().Return(
&types.NodeConfig{
Image: "alpine:3",
Expand Down
158 changes: 67 additions & 91 deletions clab/clab.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"github.com/srl-labs/containerlab/cert"
"github.com/srl-labs/containerlab/clab/dependency_manager"
errs "github.com/srl-labs/containerlab/errors"
"github.com/srl-labs/containerlab/links"
"github.com/srl-labs/containerlab/nodes"
"github.com/srl-labs/containerlab/runtime"
_ "github.com/srl-labs/containerlab/runtime/all"
Expand All @@ -26,15 +25,17 @@ import (
"github.com/srl-labs/containerlab/types"
"golang.org/x/crypto/ssh"
"golang.org/x/exp/slices"
"golang.org/x/sync/semaphore"
)

type CLab struct {
Config *Config `json:"config,omitempty"`
TopoPaths *types.TopoPaths
Nodes map[string]nodes.Node `json:"nodes,omitempty"`
Links map[int]links.Link `json:"links,omitempty"`
Endpoints []links.Endpoint
Runtimes map[string]runtime.ContainerRuntime `json:"runtimes,omitempty"`
Config *Config `json:"config,omitempty"`
TopoPaths *types.TopoPaths
m *sync.RWMutex
Nodes map[string]nodes.Node `json:"nodes,omitempty"`
Links map[int]*types.Link `json:"links,omitempty"`
Runtimes map[string]runtime.ContainerRuntime `json:"runtimes,omitempty"`
globalRuntime string
// reg is a registry of node kinds
Reg *nodes.NodeRegistry
Cert *cert.Cert
Expand All @@ -43,9 +44,7 @@ type CLab struct {
// The keys are used to enable key-based SSH access for the nodes.
SSHPubKeys []ssh.PublicKey

m *sync.RWMutex
timeout time.Duration
globalRuntime string
timeout time.Duration
}

type ClabOption func(c *CLab) error
Expand Down Expand Up @@ -166,6 +165,16 @@ func filterClabNodes(c *CLab, nodeFilter []string) error {
}
}

// filter links
for id, l := range c.Links {
for _, nodeName := range []string{l.A.Node.ShortName, l.B.Node.ShortName} {
// if both endpoints of a link belong to the node filter, keep the link
if !slices.Contains(nodeFilter, nodeName) {
delete(c.Links, id)
break
}
}
}
return nil
}

Expand All @@ -178,7 +187,7 @@ func NewContainerLab(opts ...ClabOption) (*CLab, error) {
},
m: new(sync.RWMutex),
Nodes: make(map[string]nodes.Node),
Links: make(map[int]links.Link),
Links: make(map[int]*types.Link),
Runtimes: make(map[string]runtime.ContainerRuntime),
Cert: &cert.Cert{},
}
Expand Down Expand Up @@ -410,12 +419,6 @@ func (c *CLab) scheduleNodes(ctx context.Context, maxWorkers int,
continue
}

err = node.DeployLinks(ctx)
if err != nil {
log.Errorf("failed deploy links for node %q: %v", node.Config().ShortName, err)
continue
}

// signal to dependency manager that this node is done with creation
dm.SignalDone(node.Config().ShortName, dependency_manager.NodeStateCreated)

Expand Down Expand Up @@ -499,6 +502,49 @@ func (c *CLab) WaitForExternalNodeDependencies(ctx context.Context, nodeName str
runtime.WaitForContainerRunning(ctx, c.Runtimes[c.globalRuntime], contName, nodeName)
}

// CreateLinks creates links using the specified number of workers.
func (c *CLab) CreateLinks(ctx context.Context, workers uint, dm dependency_manager.DependencyManager) {
wg := new(sync.WaitGroup)
sem := semaphore.NewWeighted(int64(workers))

for _, link := range c.Links {
wg.Add(1)
go func(li *types.Link) {
defer wg.Done()

var waitNodes []string
for _, n := range []*types.NodeConfig{li.A.Node, li.B.Node} {
// we should not wait for "host", "mgmt-net" and "macvlan" fake nodes
// as they are never managed by dependency manager (never really get created)
if n.Kind == "host" || n.ShortName == "mgmt-net" || n.Kind == "macvlan" {
continue
}
waitNodes = append(waitNodes, n.ShortName)
}

err := dm.WaitForNodes(waitNodes, dependency_manager.NodeStateCreated)
if err != nil {
log.Error(err)
}

// acquire Sem
err = sem.Acquire(ctx, 1)
if err != nil {
log.Error(err)
}
defer sem.Release(1)
// create the wiring
err = c.CreateVirtualWiring(li)
if err != nil {
log.Error(err)
}
}(link)
}

// wait for all workers to finish
wg.Wait()
}

func (c *CLab) DeleteNodes(ctx context.Context, workers uint, serialNodes map[string]struct{}) {
wg := new(sync.WaitGroup)

Expand Down Expand Up @@ -582,21 +628,6 @@ func (c *CLab) ListNodesContainers(ctx context.Context) ([]runtime.GenericContai
return containers, nil
}

// ListNodesContainersIgnoreNotFound lists all containers based on the nodes stored in clab instance, ignoring errors for non found containers
func (c *CLab) ListNodesContainersIgnoreNotFound(ctx context.Context) ([]runtime.GenericContainer, error) {
var containers []runtime.GenericContainer

for _, n := range c.Nodes {
cts, err := n.GetContainers(ctx)
if err != nil {
continue
}
containers = append(containers, cts...)
}

return containers, nil
}

func (c *CLab) GetNodeRuntime(contName string) (runtime.ContainerRuntime, error) {
shortName, err := getShortName(c.Config.Name, c.Config.Prefix, contName)
if err != nil {
Expand All @@ -613,67 +644,12 @@ func (c *CLab) GetNodeRuntime(contName string) (runtime.ContainerRuntime, error)
// VethCleanup iterates over links found in clab topology to initiate removal of dangling veths
// in host networking namespace or attached to linux bridge.
// See https://github.com/srl-labs/containerlab/issues/842 for the reference.
func (c *CLab) VethCleanup(ctx context.Context) error {
hostBasedEndpoints := []links.Endpoint{}

// collect the endpoints of regular nodes
for _, n := range c.Nodes {
if n.Config().IsRootNamespaceBased || n.Config().NetworkMode == "host" {
hostBasedEndpoints = append(hostBasedEndpoints, n.GetEndpoints()...)
}
}

// collect the endpoints of the fake nodes
hostBasedEndpoints = append(hostBasedEndpoints, links.GetHostLinkNode().GetEndpoints()...)
hostBasedEndpoints = append(hostBasedEndpoints, links.GetMgmtBrLinkNode().GetEndpoints()...)

var joinedErr error
for _, ep := range hostBasedEndpoints {
// finally remove all the collected endpoints
log.Debugf("removing endpoint %s", ep.String())
err := ep.Remove()
func (c *CLab) VethCleanup(_ context.Context) error {
for _, link := range c.Links {
err := c.RemoveHostOrBridgeVeth(link)
if err != nil {
joinedErr = errors.Join(joinedErr, err)
log.Infof("Error during veth cleanup: %v", err)
}
}

return joinedErr
}

// ResolveLinks resolves raw links to the actual link types and stores them in the CLab.Links map.
func (c *CLab) ResolveLinks() error {
// resolveNodes is a map of all nodes in the topology
// that is artificially created to combat circular dependencies.
// If no circ deps were in place we could've used c.Nodes map instead.
// The map is used to resolve links between the nodes by passing it in the ResolveParams struct.
resolveNodes := make(map[string]links.Node, len(c.Nodes))
for k, v := range c.Nodes {
resolveNodes[k] = v
}

// add the virtual host and mgmt-bridge nodes to the resolve nodes
specialNodes := map[string]links.Node{
"host": links.GetHostLinkNode(),
"mgmt-net": links.GetMgmtBrLinkNode(),
}
for _, n := range specialNodes {
resolveNodes[n.GetShortName()] = n
}

resolveParams := &links.ResolveParams{
Nodes: resolveNodes,
MgmtBridgeName: c.Config.Mgmt.Bridge,
}

for i, l := range c.Config.Topology.Links {
l, err := l.Link.Resolve(resolveParams)
if err != nil {
return err
}

c.Endpoints = append(c.Endpoints, l.GetEndpoints()...)
c.Links[i] = l
}

return nil
}
Loading

0 comments on commit 3fbb328

Please sign in to comment.