diff --git a/applications/rtdt-manager/clab-config/clab-config.go b/applications/rtdt-manager/clab-config/clab-config.go index e134e21a362b08e0ebf34b9a9c6aeef6f9099030..c3884c303a76cea7ad9d81bcee3c4fe89cfc3e84 100644 --- a/applications/rtdt-manager/clab-config/clab-config.go +++ b/applications/rtdt-manager/clab-config/clab-config.go @@ -234,6 +234,6 @@ func (c *ClabConfig) GetNodeByName(name string) *Node { return &node } } - fmt.Printf("Couldn't find a node with name %s!\n", name) + fmt.Printf("Couldn't find a node with name %s!\n", name) return nil } diff --git a/applications/rtdt-manager/main.go b/applications/rtdt-manager/main.go index fcd02133058ef724be327726dd3dffefc486dc7f..8f31ea252c8595ab5572e820cdfc95e4d2cf51fb 100644 --- a/applications/rtdt-manager/main.go +++ b/applications/rtdt-manager/main.go @@ -62,11 +62,20 @@ func main() { fmt.Printf("Error occured while trying to construct topology in realnet: %v\n", err) return } - err = realnet.CreateDevices() + err = realnet.UploadClabConfig() + if err != nil { + fmt.Printf("Error: Couldnt upload clab config: %v\n", err) + } + err = realnet.RetrieveClabConfig() if err != nil { - fmt.Printf("Error: Couldn't create devices!") - return + fmt.Printf("Error: Couldn't retrieve clab config: %v\n", err) } + return + err = realnet.CreateDevices() + if err != nil { + fmt.Printf("Error: Couldn't create devices!") + return + } err = realnet.UploadTopology() if err != nil { fmt.Printf("Error occured while trying to upload realnet topology to DB: %v\n", err) diff --git a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go index 67a40db137e64a5e4564075208ed0b7abdb89a7e..d22fa92f9994b376f251217360aa2783ce2c0269 100644 --- a/applications/rtdt-manager/rtdt-manager/rtdt-manager.go +++ b/applications/rtdt-manager/rtdt-manager/rtdt-manager.go @@ -48,12 +48,12 @@ func (r *RtdtManager) LaunchTwin(twinSubnetIPv4, twinSubnetIPv6, twinName string var derivedConfig *clabconfig.ClabConfig var clabConfigPath string var err error - var topo *rtdt_topology.Topology + var topo *rtdt_topology.Topology - topo = r.realnet.GetTopology() - if topo == nil { - return fmt.Errorf("Error: Couldn't get topology since it hasn't been retrieved from DB yet") - } + topo = r.realnet.GetTopology() + if topo == nil { + return fmt.Errorf("Error: Couldn't get topology since it hasn't been retrieved from DB yet") + } baseConfig := r.realnet.GetClabData() // Instead of deriving config do the following: @@ -283,26 +283,3 @@ func (r *RtdtManager) userEventCallback(event *event.Event) { fmt.Println("PathsAndValuesMap: ", event.PathsAndValuesMap) } -// TODO research what is actually returned from the api call -// func (rMan *RtdtManager) manageConfig(op string) error { -// switch op { -// // Import the configuration into rtdt-manager (by exporting from gosdn) -// case "import": -// fmt.Println("Now importing sdnConfig into rtdt-manager") -// confManService := confManPb.NewConfigurationManagementServiceClient(rMan.conn) -// ctx := rMan.auth.CreateContextWithAuthorization() -// exportSdnConfigResponse, err := confManService.ExportSDNConfig(ctx, &confManPb.ExportSDNConfigRequest{Timestamp: int64(time.Now().Nanosecond())}) -// if err != nil { -// return fmt.Errorf("Failed to retrieve config file of running goSDN instance: %w", err) -// } -// rMan.sdnConfig = exportSdnConfigResponse.SdnConfigData -// return nil -// // Export from rtdt-manager into gosdn controller -// case "export": -// fmt.Println("Now exporting sdnConfig into gosdn controller") -// //TODO Implement me some day -// return nil -// default: -// return fmt.Errorf("Unknown config operation") -// } -// } diff --git a/applications/rtdt-manager/venv/venv.go b/applications/rtdt-manager/venv/venv.go index ce5e4ce83eae06429682a6df3b972702736acf65..5d48751adb0049b1aeccfb11228560f9a9866178 100644 --- a/applications/rtdt-manager/venv/venv.go +++ b/applications/rtdt-manager/venv/venv.go @@ -2,12 +2,14 @@ package venv import ( "context" + "encoding/json" "fmt" "strconv" "strings" "sync" "time" + configPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/configurationmanagement" "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement" "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" topoPb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology" @@ -25,6 +27,7 @@ import ( "github.com/openconfig/ygot/ygot" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "gopkg.in/yaml.v3" ) type VEnv struct { @@ -292,6 +295,7 @@ func (v *VEnv) ApplyRoutes() error { return nil } +// TODO: Fix hardcoded IP addresses func (v *VEnv) UploadTopology() error { conn := v.auth.GetConn() topoService := topoPb.NewTopologyServiceClient(conn) @@ -317,6 +321,87 @@ func (v *VEnv) UploadTopology() error { return nil } +// What this does: Upload the nodes that make up the gosdn environment +// via the gosdn configuration service to the db (applies to db, message broker, etc.) +// This is probably not the intended use for the configuration interface? +func (v *VEnv) UploadClabConfig() error { + if v.clabData == nil { + return fmt.Errorf("Can't upload clabconfig when it hasn't been loaded yet (is nil pointer)") + } + var clabToUpload = *v.clabData + for nodename, node := range v.clabData.Topology.Nodes { + if !strings.Contains(nodename, "gosdn") && + !strings.Contains(nodename, "mongodb") && + !strings.Contains(nodename, "rabbitmq") && + !strings.Contains(nodename, "plugin-registry") { + fmt.Println("Removing node:", node) + delete(clabToUpload.Topology.Nodes, nodename) + } + } + clabToUpload.Topology.Links = nil + + clabConfig, err := yaml.Marshal(clabToUpload) + if err != nil { + return fmt.Errorf("Encountered error marshalling clabConfig: %w", err) + } + var jsonData interface{} + if err := yaml.Unmarshal(clabConfig, &jsonData); err != nil { + return fmt.Errorf("failed to unmarshal YAML to JSON: %w", err) + } + jsonBytes, err := json.MarshalIndent(jsonData, "", " ") + if err != nil { + return fmt.Errorf("Failed to marshal JSON: %w", err) + } + + req := &configPb.ImportSDNConfigRequest{ + Timestamp: util.Now(), + Pid: v.pnd.GetId(), // TODO: check if this can be nil + SdnConfigData: string(jsonBytes), + } + conn := v.auth.GetConn() + configService := configPb.NewConfigurationManagementServiceClient(conn) + ctx := v.auth.CreateContextWithAuthorization() + configResponse, err := configService.ImportSDNConfig(ctx, req) + if err != nil { + return err + } + fmt.Println("Successfully uploaded clab config:", configResponse.String()) + return nil +} + +func (v *VEnv) RetrieveClabConfig() error { + ctx := v.auth.CreateContextWithAuthorization() + conn := v.auth.GetConn() + configService := configPb.NewConfigurationManagementServiceClient(conn) + + req := &configPb.ExportSDNConfigRequest{ + Timestamp: util.Now(), + Pid: v.pnd.GetId(), + } + + configResponse, err := configService.ExportSDNConfig(ctx, req) + if err != nil { + return fmt.Errorf("Failed retrieving config clab data: %w", err) + } + var jsonData map[string]interface{} + err = json.Unmarshal([]byte(configResponse.SdnConfigData), &jsonData) + if err != nil { + return fmt.Errorf("Failed to unmarshal SDN config data: %w", err) + } + // Pretty-print the JSON data + formattedJSON, err := json.MarshalIndent(jsonData, "", " ") + if err != nil { + return fmt.Errorf("failed to format JSON data: %w", err) + } + + fmt.Println("Retrieved SDN Config Data:") + fmt.Println(string(formattedJSON)) // Print the formatted JSON + + + return nil + +} + // Topology doesn't give Kind, Image and MgmtIpv4 // For Kind: could just set linux since we don't use arista switches // For Image: möp