diff --git a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go index c012bc65f21bc5a4b6ecd2571f1070d57a4631df..723c96db2f86a9050b87d21c855b27d9c8f3a1d2 100644 --- a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go +++ b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go @@ -223,7 +223,7 @@ func (r *RtdtManager) ApplyChanges(twinName string) error { // Performance benchmarks of realnet func (r *RtdtManager) RunBenchmark0() error { var mneid string - for _, node := range r.realnet.GetTopology().Nodes { + for _, node := range r.realnet.GetSdnConfig().Nodes { if strings.HasPrefix(node.Name, "gnmi-target-switch0") { mneid = node.ID } @@ -434,7 +434,7 @@ func (r *RtdtManager) updateMNECallback(event *event.Event) { err = twin.SetGnmiPath(path, value, twinEntityID, false) if err != nil { fmt.Println("Callback failed:", err) - return + return } } } diff --git a/applications/rtdt-manager/rtdt-topology/rtdt-topology.go b/applications/rtdt-manager/rtdt-topology/rtdt-topology.go deleted file mode 100644 index 13b93710a1bb00de8dd9ddea5cfc9307a814340e..0000000000000000000000000000000000000000 --- a/applications/rtdt-manager/rtdt-topology/rtdt-topology.go +++ /dev/null @@ -1,270 +0,0 @@ -package rtdt_topology - -import ( - "fmt" - "regexp" - "strings" - - topoPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology" - clabconfig "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config" - rtdt_auth "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/rtdt-auth" - "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/util" - "code.fbi.h-da.de/danet/gosdn/models/generated/openconfig" -) - -// Struct definitions were taken from: -// "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/topology/port.go" -// "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/topology/link.go" -// "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/topology/node.go" -// commit: 0264b698286b6cbb965d743078c681f8af55edf6 -type Link struct { - ID string - Name string - SourceNode *Node - TargetNode *Node - SourcePort *Port - TargetPort *Port -} -type Port struct { - ID string - Name string -} - -type Node struct { - ID string - Name string - Kind string - Image string - MgmtIpv4 string - YangData openconfig.Device -} - -type Topology struct { - Links []*Link - Ports []*Port - Nodes []*Node -} - -func NewTopology() *Topology { - return &Topology{} -} - -func (t *Topology) GetNodeByUUID(UUID string) *Node { - for _, node := range t.Nodes { - if node.ID == UUID { - return node - } - } - return nil -} - -func (t *Topology) GetNodeByName(name string) *Node { - for _, node := range t.Nodes { - if node.Name == name { - return node - } - } - return nil -} - -func (t *Topology) GetPortByUUID(UUID string) *Port { - for _, port := range t.Ports { - if port.ID == UUID { - return port - } - } - return nil -} -func (t *Topology) GetLinkByUUID(UUID string) *Link { - for _, link := range t.Links { - if link.ID == UUID { - return link - } - } - return nil -} - -// Source for function: "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/link.go" -// commit: 0264b698286b6cbb965d743078c681f8af55edf6 -// GetLinkAsSliceOfStrings returns the link as a slice of strings for yaml representation. -func (l *Link) GetLinkAsSliceOfStrings() [2]string { - return [2]string{l.SourceNode.Name + ":" + l.SourcePort.Name, l.TargetNode.Name + ":" + l.TargetPort.Name} -} - -// Source for function: "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/node.go" -// commit: 0264b698286b6cbb965d743078c681f8af55edf6 -// FillAllFields fills all remaining fields of object with data from YangData. -func (n *Node) FillAllFields(containerRegistryURL string) { - // Works if linux and our gnmi target is used. - softwareVersion := n.YangData.System.State.SoftwareVersion - if softwareVersion != nil { - // Checks if software version is in compatible format. - result, _ := regexp.MatchString(`^([A-Za-z0-9\.\/])*:([A-Za-z0-9\.])*`, *softwareVersion) - if result { - n.Kind = "linux" - n.Image = containerRegistryURL + *softwareVersion - return - } - - n.Kind = "couldn't detect kind" - n.Image = "couldn't detect image" - return - } - - // Specific to arista - regex := regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9][A-Z]`) - dockerTag := string(regex.FindAll([]byte(*n.YangData.Lldp.Config.SystemDescription), 1)[0]) - - // If it's not linux with our gnmi target and not arista, we don't support it. - if len(dockerTag) == 0 { - n.Kind = "couldn't detect kind" - n.Image = "couldn't detect image" - return - } - - n.Kind = "ceos" - n.Image = containerRegistryURL + n.Kind + ":" + dockerTag -} - -// Based on the given auth and a pnd, get a topology from the DB store -func (t *Topology) RetrieveTopology(pnd string, auth *rtdt_auth.RtdtAuth) error { - conn := auth.GetConn() - ctx := auth.CreateContextWithAuthorization() - topoService := topoPb.NewTopologyServiceClient(conn) - topoResponse, err := topoService.GetTopology(ctx, &topoPb.GetTopologyRequest{Timestamp: util.Now()}) - if err != nil { - return fmt.Errorf("Couldn't retrieve topology from DB: %v\n", err) - } - sourceTopo := topoResponse.GetToplogy() - targetTopo := NewTopology() - for _, link := range sourceTopo.Links { - var n0 Node - var n1 Node - if targetTopo.GetNodeByUUID(link.SourceNode.Id) == nil { - snode := link.SourceNode - n0 = Node{ - ID: snode.Id, - Name: snode.Name, - Kind: "todo", - Image: "todo", // How to do this? - MgmtIpv4: "todo", - } - // n0.FillAllFields(containerRegistryURL) // TODO get this later - t.Nodes = append(t.Nodes, &n0) - } - if targetTopo.GetNodeByUUID(link.TargetNode.Id) == nil { - tnode := link.TargetNode - n1 = Node{ - ID: tnode.Id, - Name: tnode.Name, - Kind: "todo", - Image: "todo", // How to do this? - MgmtIpv4: "todo", - } - //n1.FillAllFields(v.containerRegistryURL) - t.Nodes = append(t.Nodes, &n1) - } - if targetTopo.GetLinkByUUID(link.Id) == nil { - var p0 Port - var p1 Port - - if targetTopo.GetPortByUUID(link.SourcePort.Id) == nil { - p0 = Port{ - Name: link.SourcePort.Name, - ID: link.SourcePort.Id, - } - } - if targetTopo.GetPortByUUID(link.SourcePort.Id) == nil { - p1 = Port{ - Name: link.TargetPort.Name, - ID: link.TargetPort.Id, - } - } - - var newLink = Link{ - ID: link.Id, - Name: link.Name, - SourceNode: &n0, - TargetNode: &n1, - SourcePort: &p0, - TargetPort: &p1, - } - t.Links = append(t.Links, &newLink) - } - } - - return nil - -} - -func (t *Topology) ToYAML() *clabconfig.ClabConfig { - var yamlMgmt clabconfig.Mgmt - var yamlNodes map[string]clabconfig.Node - var yamlLinks []clabconfig.Link - - // First get topology information, meaning gnmi-targets and hosts - for _, n := range t.Nodes { - // TODO This is very ugly, for now just fill in missing data based on name of node - var cmd string - var binds []string - var ports []string - var env map[string]string - var startupDelay int - switch { - case strings.Contains(n.Name, "gnmi-target"): - cmd = "start --ca_file /etc/gnmi-target/ssl/ca.crt --cert /etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt --key /etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key" - binds = []string{"../../../artifacts/ssl/gnmi-target", "/etc/gnmi-target/ssl"} - startupDelay = 5 - case strings.Contains(n.Name, "gosdn"): - cmd = "--config /app/configs/containerlab-gosdn.toml" - binds = []string{"../../../artifacts/ssl/gosdn", "/app/ssl"} - } - node := clabconfig.Node{ - Kind: n.Kind, - Image: n.Image, - Ports: ports, - Cmd: cmd, - MgmtIPv4: n.MgmtIpv4, - Env: env, - Binds: binds, - StartupDelay: startupDelay, - Group: "", - } - yamlNodes[n.Name] = node - } - - // Now: Get configuration for environment (controller, rabbitmq, mongodb) somehow.. - - return &clabconfig.ClabConfig{ - Name: "", - Mgmt: yamlMgmt, - Topology: clabconfig.Topology{ - Nodes: yamlNodes, - Links: yamlLinks, - }, - } -} - -// Converter functions to convert between this and topoPb version of topology -func (n *Node) Convert() *topoPb.Node { - return &topoPb.Node{ - Id: n.ID, - Name: n.Name, - } -} -func (p *Port) Convert() *topoPb.Port { - return &topoPb.Port{ - Id: p.ID, - Name: p.Name, - } -} -func (l *Link) Convert() *topoPb.Link { - return &topoPb.Link{ - Id: l.ID, - Name: l.Name, - SourceNode: l.SourceNode.Convert(), - SourcePort: l.SourcePort.Convert(), - TargetNode: l.TargetNode.Convert(), - TargetPort: l.TargetPort.Convert(), - } -} diff --git a/applications/rtdt-manager/venv/venv.go b/applications/rtdt-manager/venv/venv.go index 2e7a941a99522d4ba75008986f73e02c1e66f6ac..0c2caecb00a88a7728996dddb1bb5153510d83b7 100644 --- a/applications/rtdt-manager/venv/venv.go +++ b/applications/rtdt-manager/venv/venv.go @@ -19,12 +19,9 @@ import ( clabconfig "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config" "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/gosdnutil" rtdt_auth "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/rtdt-auth" - rtdt_topology "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/rtdt-topology" "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/sdnconfig" "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/util" gnmitargetygot "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/yang" - yangparser "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/yang-parser" - "code.fbi.h-da.de/danet/gosdn/models/generated/openconfig" uuid "github.com/google/uuid" gnmi "github.com/openconfig/gnmi/proto/gnmi" "github.com/openconfig/ygot/ygot" @@ -40,8 +37,7 @@ type VEnv struct { pnd *pnd.PrincipalNetworkDomain clabData *clabconfig.ClabConfig // Represents yaml file that was used to deploy sdnConfig *sdnconfig.SdnConfig // Represents json config file for configuration grpc interface - topology *rtdt_topology.Topology - clabFilename string // This is the name of the yaml file clabData is based on + clabFilename string // This is the name of the yaml file clabData is based on StopChan <-chan struct{} waitGroup *sync.WaitGroup containerRegistryURL string @@ -119,7 +115,6 @@ func NewVEnv(name, clabFilename, user, pass string, wg *sync.WaitGroup, sdnConfi clabData: clabData, clabFilename: clabFilename, waitGroup: wg, - topology: nil, // set this later sdnConfig: sdnConfig, containerRegistryURL: "registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test", // TODO: Could let user choose } @@ -178,7 +173,7 @@ func (v *VEnv) CreateDevices() error { // Source: "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/venv-manager/venv-manager.go" // commit: 0264b698286b6cbb965d743078c681f8af55edf6 -func (v *VEnv) loadNetworkElementModelPathsIntoGosdn(ctx context.Context, conn *grpc.ClientConn, nodes *[]*rtdt_topology.Node) error { +func (v *VEnv) loadNetworkElementModelPathsIntoGosdn(ctx context.Context, conn *grpc.ClientConn, nodes *[]*sdnconfig.Node) error { networkElementService := networkelement.NewNetworkElementServiceClient(conn) paths := [2]string{"/lldp/config/system-description", "/system/state/"} @@ -193,106 +188,10 @@ func (v *VEnv) loadNetworkElementModelPathsIntoGosdn(ctx context.Context, conn * return nil } -// Based on getAndAddMoreData() in: "code.fbi.h-da.de/danet/gosdn/applications/venv-manager/venv-manager/venv-manager.go" -// commit: 0264b698286b6cbb965d743078c681f8af55edf6 -// What this does: Load yang paths into topo, then iterate over -// nodes and fill data in -func (v *VEnv) ConstructTopology() error { - if v.clabData == nil { - return fmt.Errorf("Error: Trying to construct topology without containerlab file being loaded first") - } - // Either fill topology from clabData or from database? - ctx := v.auth.CreateContextWithAuthorization() - conn := v.conn - var path = "/" - var ygotPath *gnmi.Path - - // Create 'root' path to be able to load the whole model from the store. - var err error - ygotPath, err = ygot.StringToPath(path, ygot.StructuredPath) - if err != nil { - return err - } - - // just to load model data into goSDN to guaranteed have new data available for get request - err = v.loadNetworkElementModelPathsIntoGosdn(ctx, conn, &v.topology.Nodes) - if err != nil { - return err - } - - networkElementService := networkelement.NewNetworkElementServiceClient(conn) - - for iterator, node := range v.topology.Nodes { - getNetworkElementResponse, _ := networkElementService.Get(ctx, &networkelement.GetRequest{Mneid: node.ID}) - if err != nil { - return err - } - - var marshalledYangData openconfig.Device - - err = yangparser.Unmarshal([]byte(getNetworkElementResponse.Mne.Model), ygotPath, &marshalledYangData) - if err != nil { - return err - } - - mgmntAddress := strings.Split(getNetworkElementResponse.Mne.TransportAddress, ":") - v.topology.Nodes[iterator].MgmtIpv4 = mgmntAddress[0] - v.topology.Nodes[iterator].YangData = marshalledYangData - v.topology.Nodes[iterator].FillAllFields(v.containerRegistryURL) - } - - return nil -} - -// Create rtdt_topology.Topology from clabconfig.Topology -func (v *VEnv) DeriveTopologyFromClabData() error { - if v.clabData == nil { - return fmt.Errorf("Can't derive topology without clabData\n") - } - v.topology = &rtdt_topology.Topology{} - var topoNodes []*rtdt_topology.Node - // Get all the nodes from clab structure - for nodeName, node := range v.clabData.Topology.Nodes { - topoNode := rtdt_topology.Node{ - ID: uuid.NewString(), - Name: nodeName, - Kind: node.Kind, - Image: node.Image, - MgmtIpv4: node.MgmtIPv4, - } - topoNodes = append(topoNodes, &topoNode) - } - v.topology.Nodes = topoNodes - for _, link := range v.clabData.Topology.Links { - if len(link.Endpoints) != 2 { - return fmt.Errorf("Couldn't parse clabData into topology\n") - } - var topoLink = rtdt_topology.Link{} - // determine Node name and port - node0Full := strings.Split(link.Endpoints[0], ":") - node0Name := node0Full[0] - node0Port := node0Full[1] - node1Full := strings.Split(link.Endpoints[1], ":") - node1Name := node1Full[0] - node1Port := node1Full[1] - - // find the node that has right name, add links and ports - topoLink.SourceNode = v.topology.GetNodeByName(node0Name) - topoLink.SourcePort = &rtdt_topology.Port{Name: node0Port, ID: uuid.NewString()} - v.topology.Ports = append(v.topology.Ports, topoLink.SourcePort) - topoLink.TargetNode = v.topology.GetNodeByName(node1Name) - topoLink.TargetPort = &rtdt_topology.Port{Name: node1Port, ID: uuid.NewString()} - v.topology.Ports = append(v.topology.Ports, topoLink.TargetPort) - v.topology.Links = append(v.topology.Links, &topoLink) - v.topology.Nodes = topoNodes - } - return nil -} - func (v *VEnv) ApplyRoutes() error { conn := v.auth.GetConn() hostIP := int64(1) - for _, link := range v.topology.Links { + for _, link := range v.sdnConfig.Links { req := topoPb.AddRoutingTableRequest{ Timestamp: util.Now(), RoutingTable: &topoPb.RoutingTable{ @@ -508,9 +407,6 @@ func (v VEnv) GetAuth() *rtdt_auth.RtdtAuth { func (v *VEnv) GetWaitgroup() *sync.WaitGroup { return v.waitGroup } -func (v *VEnv) GetTopology() *rtdt_topology.Topology { - return v.topology -} func (v *VEnv) GetSdnConfig() *sdnconfig.SdnConfig { return v.sdnConfig }