diff --git a/applications/rtdt-manager/data/gosdn_slim.clab.yaml b/applications/rtdt-manager/data/realnet-clab.yaml similarity index 98% rename from applications/rtdt-manager/data/gosdn_slim.clab.yaml rename to applications/rtdt-manager/data/realnet-clab.yaml index 860448226b9ca3368bbfb7148525170278fca5bc..ea3c9f1745495451b2e41b179eb434cf53635089 100644 --- a/applications/rtdt-manager/data/gosdn_slim.clab.yaml +++ b/applications/rtdt-manager/data/realnet-clab.yaml @@ -29,7 +29,7 @@ topology: gnmi-target-switch0: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test #only for local use #image: gnmi-target:latest binds: @@ -42,7 +42,7 @@ topology: gnmi-target-switch1: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test #only for local use #image: gnmi-target:latest binds: diff --git a/applications/rtdt-manager/data/twin-clab.yaml b/applications/rtdt-manager/data/twin-clab.yaml index c6e575598e016f4170c13612c46608c18dd4be17..db8fd02bcec3f8cfe109b0b24ba14a8903960c86 100644 --- a/applications/rtdt-manager/data/twin-clab.yaml +++ b/applications/rtdt-manager/data/twin-clab.yaml @@ -18,7 +18,7 @@ topology: group: server gnmi-target-switch0: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test ports: - 7035:7030 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 @@ -28,7 +28,7 @@ topology: startup-delay: 5 gnmi-target-switch1: kind: linux - image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master + image: registry.code.fbi.h-da.de/danet/gnmi-target/debian:interface-enabled-test ports: - 7036:7030 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 diff --git a/applications/rtdt-manager/gosdnutil/gosdnutil.go b/applications/rtdt-manager/gosdnutil/gosdnutil.go index 0067898d65ed69c180dca75e6a0e802fee53be59..95386c30d535705a57893a5f077737d958e23ce1 100644 --- a/applications/rtdt-manager/gosdnutil/gosdnutil.go +++ b/applications/rtdt-manager/gosdnutil/gosdnutil.go @@ -36,7 +36,7 @@ func AddNetworkElement(rtdtAuth *rtdt_auth.RtdtAuth, addr, mneName, mneUUID stri // Here wee use the pb generated code directly instead of using nbi mneClient := mnepb.NewNetworkElementServiceClient(rtdtAuth.GetConn()) - req := &mnepb.AddListRequest{ + request := &mnepb.AddListRequest{ Timestamp: time.Now().UnixNano(), Mne: []*mnepb.SetMne{ { @@ -53,10 +53,11 @@ func AddNetworkElement(rtdtAuth *rtdt_auth.RtdtAuth, addr, mneName, mneUUID stri } switch t := opt.Type; t { case spb.Type_TYPE_CONTAINERISED, spb.Type_TYPE_PLUGIN: - req.Mne[0].TransportOption.Type = t + request.Mne[0].TransportOption.Type = t default: } - listResponse, err := mneClient.AddList(rtdtAuth.CreateContextWithAuthorization(), req) + fmt.Println("DEBUG: in AddNetworkElement, request is:", request) + listResponse, err := mneClient.AddList(rtdtAuth.CreateContextWithAuthorization(), request) // Return AddListResponse return listResponse, err } diff --git a/applications/rtdt-manager/main.go b/applications/rtdt-manager/main.go index 5926b54c321ad27c93ef3223914862cc1dae29ba..54c2d55efe2e8a2b9914f1ea46871f0ca9d71924 100644 --- a/applications/rtdt-manager/main.go +++ b/applications/rtdt-manager/main.go @@ -58,11 +58,11 @@ func main() { fmt.Println("Couldn't initialize rtdt-manager, quitting!") return } - // err := rtdtMan.InitEventSystem() - // if err != nil { - // fmt.Printf("Error occured while initializing event system: %v", err) - // return - // } + err := rtdtMan.InitEventSystem() + if err != nil { + fmt.Printf("Error occured while initializing event system: %v", err) + return + } if withTwin { rtdtMan.LaunchTwin("172.101.0.0/16", "2001:db9::/64", "TEST-TWIN") } diff --git a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go index e3ea4bb1f79ef77ed309b873b1354ba592498926..da1d86eeba2bf80bbd573a65aff7f54e85278130 100644 --- a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go +++ b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go @@ -1,13 +1,15 @@ package rtdtmanager import ( - "code.fbi.h-da.de/danet/gosdn/application-framework/event" "fmt" "os" "path/filepath" + "regexp" "strings" "sync" + "code.fbi.h-da.de/danet/gosdn/application-framework/event" + "code.fbi.h-da.de/danet/gosdn/application-framework/registration" clabconfig "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/clab-config" "code.fbi.h-da.de/danet/gosdn/applications/rtdt-manager/venv" @@ -55,9 +57,6 @@ func (r *RtdtManager) LaunchTwin(twinSubnetIPv4, twinSubnetIPv6, twinName string return fmt.Errorf("Failed to write modified twin clab config to disk: %w", err) } - // Now run deploy with new config file - // user := r.realnet.GetAuth().GetUsername() - // password := r.realnet.GetAuth().GetPassword() twin := venv.NewVEnv(twinName, clabConfigFullPath, "admin", "TestPassword", r.waitGroup) r.rtdt_twins = append(r.rtdt_twins, twin) return nil @@ -161,24 +160,40 @@ func (r *RtdtManager) updateMNECallback(event *event.Event) { //realnetClabData := r.realnet.GetClabData() // for i, node := range realnetClabData.Topology.Nodes { // } - suffix := "]/config/mtu" - //re := regexp.MustCompile(`/interfaces/interface\[name=([^]]+)]/state/oper-status`) + suffixMTU := "]/config/mtu" - // Apply event to a twin - // No twins to apply changes to: - if len(r.rtdt_twins) == 0 { - fmt.Println("--- NO TWINS TO APPLY CHANGE TO ---") + // Select a twin + //TODO: This is where some selection process should happen to select the right twin based on the event + var twin *venv.VEnv + if len(r.rtdt_twins) > 0 { + twin = r.rtdt_twins[0] // just support one twin for now + } else { + fmt.Println("Event triggered but no twin to apply it to exists (yet)") return } + // Test if the path is supported first, only set Gnmi Paths I actually want to be able to set for now for path, value := range event.PathsAndValuesMap { - if strings.HasPrefix(path, prefix) && strings.HasSuffix(path, suffix) { + // Based on EntityID, get the gnmi target from twin's ClabConfig + // First get hostname of realnet node + realnetNode := r.realnet.GetTopology().GetNodeByUUID(event.EntityID.String()) + + var twinEntityID string + for _, node := range twin.GetTopology().Nodes { + if strings.HasPrefix(node.Name, realnetNode.Name) { + twinEntityID = node.ID + } + } + + if strings.HasPrefix(path, prefix) && strings.HasSuffix(path, suffixMTU) { fmt.Println("--- CHANGE MTU TRIGGERED ---") fmt.Println("Value of new MTU: ", value) + // TODO: ONLY APPLY THIS TO A RELEVANT TWIN for _, twin := range r.rtdt_twins { - twin.SetGnmiPath(path, value, event.EntityID.String()) + twin.SetGnmiPath(path, value, twinEntityID) } } + // Hostname change if strings.HasPrefix(path, prefixHostname) { fmt.Println("--- CHANGE HOSTNAME TRIGGERED ---") for _, twin := range r.rtdt_twins { @@ -187,9 +202,18 @@ func (r *RtdtManager) updateMNECallback(event *event.Event) { continue } fmt.Println("ENTERING SETGNMIPATH, value: ", value, "path:", path) - twin.SetGnmiPath(path, value, event.EntityID.String()) + twin.SetGnmiPath(path, value, twinEntityID) } } + // LINK UP/DOWN + re := regexp.MustCompile(`/interfaces/interface\[name=([^]]+)]/state/oper-status`) + match := re.FindStringSubmatch(path) + if match != nil && len(r.rtdt_twins) > 0 { + fmt.Println("Setting interface", match[1], "UP/DOWN") + fmt.Printf("match: %v\n", match) + path := "/interfaces/interface[name=" + match[1] + "]/config/enabled" + r.rtdt_twins[0].SetGnmiPath(path, value, twinEntityID) + } } } func (r *RtdtManager) userEventCallback(event *event.Event) { diff --git a/applications/rtdt-manager/rtdt-topology/rtdt-topology.go b/applications/rtdt-manager/rtdt-topology/rtdt-topology.go index 171ab72e87923ddafac69fcc99a744229c015fc5..d4123f10eab7eb6727cf7ba318c4cb7f19c3bc9c 100644 --- a/applications/rtdt-manager/rtdt-topology/rtdt-topology.go +++ b/applications/rtdt-manager/rtdt-topology/rtdt-topology.go @@ -1,8 +1,8 @@ package rtdt_topology import ( - "regexp" "code.fbi.h-da.de/danet/gosdn/models/generated/openconfig" + "regexp" ) // Struct definitions were taken from: @@ -43,6 +43,15 @@ 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 +} + // 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. diff --git a/applications/rtdt-manager/util/util.go b/applications/rtdt-manager/util/util.go index ec1e048dc672de7798d2f029c137b1a6bffa2b1c..48cc23af6469938166469ecfbf63df636db8df77 100644 --- a/applications/rtdt-manager/util/util.go +++ b/applications/rtdt-manager/util/util.go @@ -9,7 +9,7 @@ import ( ) func Now() int64 { - return int64(time.Now().Nanosecond()) + return int64(time.Now().UnixNano()) } func GenerateGosdnPath() (string, error) { diff --git a/applications/rtdt-manager/venv/venv.go b/applications/rtdt-manager/venv/venv.go index 4dfdacabab111045e715c2148febda8db1c420d3..19ed241255bf6bb1a4f86ffd4882da5f102e793d 100644 --- a/applications/rtdt-manager/venv/venv.go +++ b/applications/rtdt-manager/venv/venv.go @@ -3,6 +3,7 @@ package venv import ( "context" "fmt" + "strconv" "strings" "sync" "time" @@ -66,8 +67,8 @@ func NewVEnv(name, topoYamlFile, user, pass string, wg *sync.WaitGroup) *VEnv { } } - fmt.Printf("[%s] - Sleep for 10 seconds to give containers time to settle..\n", name) - time.Sleep(time.Second * 10) + fmt.Printf("[%s] - Sleep for 15 seconds to give containers time to settle..\n", name) + time.Sleep(time.Second * 15) // Now log into gosdn physical network dialOption := grpc.WithTransportCredentials(insecure.NewCredentials()) gosdnconn, err := grpc.NewClient(gosdnAddress, dialOption, grpc.WithDefaultCallOptions()) @@ -91,22 +92,12 @@ func NewVEnv(name, topoYamlFile, user, pass string, wg *sync.WaitGroup) *VEnv { if err == nil { break } - gosdnconn.Close() - gosdnconn, err = grpc.NewClient(gosdnAddress, dialOption, grpc.WithDefaultCallOptions()) - if err != nil { - fmt.Println("All is over") - return nil - } - gosdnauth = rtdt_auth.NewRtdtAuth("admin", "172.101.0.5:55055", "TestPassword", gosdnconn) - - fmt.Printf("[%s] - Failed to fetch pnd from venv: %v, retrying\n", name, err) - time.Sleep(time.Second * 150) + fmt.Printf("[%s] - Couldn't retrieve PND, retrying in 2 seconds..", name) + time.Sleep(time.Second * 2) } // Sleep before adding devices because otherwise it won't work // Apply the topoYamlFile: we need to register the switches with the controller - fmt.Printf("[%s] - Sleep for 7 more seconds to give containers time to settle before creating mne..\n", name) - time.Sleep(time.Second * 7) var topo rtdt_topology.Topology var topoNodes []rtdt_topology.Node for node, val := range clabData.Topology.Nodes { @@ -136,9 +127,7 @@ func NewVEnv(name, topoYamlFile, user, pass string, wg *sync.WaitGroup) *VEnv { fmt.Printf("[%s] - Found target: %s with addr: %s\n", name, node, addr) fmt.Printf("[%s] - Gosdn controller at %s\n", name, gosdnAddress) - //listResponse, err := api.AddNetworkElement(ctx, val.MgmtIPv4+":7030", node, "", opt, mneUUID, pid, []string{"/"}) listResponse, err := gosdnutil.AddNetworkElement(gosdnauth, gosdnAddress, node, "", opt, pluginID, pndID, []string{"/"}) - //listResponse, err := api.AddNetworkElement(ctx, gosdnAddress, node, "", opt, pluginID, pndID, []string{"/interfaces"}) if err != nil { fmt.Printf("[%s] - Failed to add network elements: %v\n", name, err) return nil @@ -230,6 +219,16 @@ func (v *VEnv) ConstructTopology() error { return nil } +func getTypedValue(value string) *gnmi.TypedValue { + if boolVal, err := strconv.ParseBool(value); err == nil { + return &gnmi.TypedValue{Value: &gnmi.TypedValue_BoolVal{BoolVal: boolVal}} + } else if intVal, err := strconv.ParseInt(value, 10, 64); err == nil { + return &gnmi.TypedValue{Value: &gnmi.TypedValue_IntVal{IntVal: intVal}} + } else { + return &gnmi.TypedValue{Value: &gnmi.TypedValue_StringVal{StringVal: value}} + } +} + func (v *VEnv) SetGnmiPath(path, value, mneid string) error { ctx := v.auth.CreateContextWithAuthorization() fmt.Println("--IN SETGNMIPATH-----------------------") @@ -239,24 +238,25 @@ func (v *VEnv) SetGnmiPath(path, value, mneid string) error { return fmt.Errorf("Encountered error while trying to parse string path into gnmi path: %w", err) } //gosdnAddr := v.auth.GetAddress() - fmt.Println("Got to setting pid from v.pnd.Id") - pid := v.pnd.Id - gnmiVal := gnmi.TypedValue{} - req := &networkelement.ChangeRequest{ + gnmiVal := getTypedValue(value) + + request := &networkelement.ChangeRequest{ Mneid: mneid, Path: gnmiPath, - Value: &gnmiVal, + Value: gnmiVal, ApiOp: networkelement.ApiOperation_API_OPERATION_UPDATE, } - changeRequests := []*networkelement.ChangeRequest{req} + changeRequests := []*networkelement.ChangeRequest{request} + pid := v.pnd.Id setPathResponse, err := mneService.SetPathList(ctx, &networkelement.SetPathListRequest{ Timestamp: util.Now(), Pid: pid, ChangeRequest: changeRequests, }) if err != nil { + fmt.Printf("Going to panic now, the 'setPathResponse' value is %v\n", setPathResponse.String()) panic(err) } fmt.Println("setPathResponse: ", setPathResponse.String())