Add topology-parser tool.
[oam.git] / code / network-topology-parser / main.go
diff --git a/code/network-topology-parser/main.go b/code/network-topology-parser/main.go
new file mode 100644 (file)
index 0000000..6fdbf38
--- /dev/null
@@ -0,0 +1,218 @@
+/************************************************************************
+* Copyright 2022 highstreet technologies GmbH
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+************************************************************************/
+
+package main
+
+import (
+       "encoding/json"
+       "errors"
+       "fmt"
+       "io/ioutil"
+       "os"
+
+       "github.com/goccy/go-yaml"
+)
+
+var configYAML Config
+
+// common parts consist of the anchors that are reused for the services
+func createCommonParts() {
+       configYAML.Version = "3.8"
+
+       configYAML.CommonEnvs = make(map[string]string, 1)
+
+       configYAML.CommonEnvs["IPv6_ENABLED"] = "${IPv6_ENABLED}"
+       configYAML.CommonEnvs["SSH_CONNECTIONS"] = "${SSH_CONNECTIONS}"
+       configYAML.CommonEnvs["TLS_CONNECTIONS"] = "${TLS_CONNECTIONS}"
+       configYAML.CommonEnvs["NTS_NF_MOUNT_POINT_ADDRESSING_METHOD"] = "${NTS_NF_MOUNT_POINT_ADDRESSING_METHOD}"
+       configYAML.CommonEnvs["NTS_HOST_IP"] = "${NTS_HOST_IP}"
+       configYAML.CommonEnvs["NTS_HOST_BASE_PORT"] = "${NTS_HOST_BASE_PORT}"
+       configYAML.CommonEnvs["NTS_HOST_NETCONF_SSH_BASE_PORT"] = "${NTS_HOST_NETCONF_SSH_BASE_PORT}"
+       configYAML.CommonEnvs["NTS_HOST_NETCONF_TLS_BASE_PORT"] = "${NTS_HOST_NETCONF_TLS_BASE_PORT}"
+       configYAML.CommonEnvs["NTS_HOST_TRANSFER_FTP_BASE_PORT"] = "${NTS_HOST_TRANSFER_FTP_BASE_PORT}"
+       configYAML.CommonEnvs["NTS_HOST_TRANSFER_SFTP_BASE_PORT"] = "${NTS_HOST_TRANSFER_SFTP_BASE_PORT}"
+       configYAML.CommonEnvs["SDN_CONTROLLER_PROTOCOL"] = "${SDN_CONTROLLER_PROTOCOL}"
+       configYAML.CommonEnvs["SDN_CONTROLLER_IP"] = "${SDNC_OAM_IPv6}"
+       configYAML.CommonEnvs["SDN_CONTROLLER_PORT"] = "${SDNC_REST_PORT}"
+       configYAML.CommonEnvs["SDN_CONTROLLER_CALLHOME_IP"] = "${SDNC_OAM_IPv6}"
+       configYAML.CommonEnvs["SDN_CONTROLLER_CALLHOME_PORT"] = "${SDN_CONTROLLER_CALLHOME_PORT}"
+       configYAML.CommonEnvs["SDN_CONTROLLER_USERNAME"] = "${ADMIN_USERNAME}"
+       configYAML.CommonEnvs["SDN_CONTROLLER_PASSWORD"] = "${ADMIN_PASSWORD}"
+       configYAML.CommonEnvs["VES_COMMON_HEADER_VERSION"] = "${VES_COMMON_HEADER_VERSION}"
+       configYAML.CommonEnvs["VES_ENDPOINT_PROTOCOL"] = "${VES_ENDPOINT_PROTOCOL}"
+       configYAML.CommonEnvs["VES_ENDPOINT_IP"] = "${VES_COLLECTOR_OAM_IPv6}"
+       configYAML.CommonEnvs["VES_ENDPOINT_PORT"] = "${VES_ENDPOINT_PORT}"
+       configYAML.CommonEnvs["VES_ENDPOINT_AUTH_METHOD"] = "${VES_ENDPOINT_AUTH_METHOD}"
+       configYAML.CommonEnvs["VES_ENDPOINT_USERNAME"] = "${VES_ENDPOINT_USERNAME}"
+       configYAML.CommonEnvs["VES_ENDPOINT_PASSWORD"] = "${VES_ENDPOINT_PASSWORD}"
+
+       configYAML.DuEnv = make(map[string]string, 1)
+       configYAML.DuEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate ves-heartbeat ves-file-ready ves-pnf-registration web-cut-through"
+
+       configYAML.RuEnv = make(map[string]string, 1)
+       configYAML.RuEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate netconf-call-home web-cut-through"
+
+       configYAML.TopoEnv = make(map[string]string, 1)
+       configYAML.TopoEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate netconf-call-home web-cut-through"
+
+       var commonNf CommonNf
+       commonNf.StopGracePeriod = "5m"
+       commonNf.CapAdd = append(commonNf.CapAdd, "SYS_ADMIN")
+       commonNf.CapAdd = append(commonNf.CapAdd, "SYS_PTRACE")
+       configYAML.CommonNfs = commonNf
+}
+
+// creates the network information to be used by the services
+func createNetwork() {
+       configYAML.Networks = make(map[string]Network, 1)
+       defaultNetwork := configYAML.Networks["default"]
+
+       defaultNetwork.External = make(map[string]string, 1)
+       defaultNetwork.External["name"] = "oam"
+
+       configYAML.Networks["default"] = defaultNetwork
+}
+
+// creates an O-RU simulator instance as a service
+func addORUasService(name string) {
+       service := configYAML.Services[name]
+
+       service.Image = "${NEXUS3_DOCKER_REPO}nts-ng-o-ran-ru-fh:${NTS_BUILD_VERSION}"
+       service.ContainerName = "ntsim-ng-" + name
+       service.Hostname = name
+
+       commonEnv := &CommonEnv{}
+       ruEnv := &RuEnv{}
+       env := &Env{commonEnv, nil, ruEnv, nil}
+       service.Environment = *env
+
+       configYAML.Services[name] = service
+}
+
+// creates an O-DU simulator instance as a service
+func addODUasService(name string) {
+       service := configYAML.Services[name]
+
+       service.Image = "${NEXUS3_DOCKER_REPO}nts-ng-o-ran-du:${NTS_BUILD_VERSION}"
+       service.ContainerName = "ntsim-ng-" + name
+       service.Hostname = name
+
+       commonEnv := &CommonEnv{}
+       duEnv := &DuEnv{}
+       env := &Env{commonEnv, duEnv, nil, nil}
+       service.Environment = *env
+
+       configYAML.Services[name] = service
+}
+
+// iterates through the topology and creates associated services
+func createServices(topologyJSON *TapiContext) {
+       topology := topologyJSON.TapiCommonContext.TapiTopologyTopologyContext.Topology[0]
+
+       configYAML.Services = make(map[string]Service, 1)
+
+       for _, node := range topology.Node {
+               if node.ORanScTopologyFunction == "o-ran-sc-topology-common:o-ru" {
+                       name := getNodeNameFromUUID(node.UUID, topologyJSON)
+                       addORUasService(name)
+               } else if node.ORanScTopologyFunction == "o-ran-sc-topology-common:o-du" {
+                       name := getNodeNameFromUUID(node.UUID, topologyJSON)
+                       addODUasService(name)
+               }
+       }
+}
+
+// returns the type of O-RAN-SC Topology Function of the input TAPI Node
+func getTypeOfNodeUUID(nodeUUID string, topologyJSON *TapiContext) string {
+       topology := topologyJSON.TapiCommonContext.TapiTopologyTopologyContext.Topology[0]
+
+       for _, node := range topology.Node {
+               if node.UUID == nodeUUID {
+                       return node.ORanScTopologyFunction
+               }
+       }
+
+       return ""
+}
+
+// returns the Node Name of the TAPI Node with the input UUID
+func getNodeNameFromUUID(searchedUUID string, topologyJSON *TapiContext) string {
+       topology := topologyJSON.TapiCommonContext.TapiTopologyTopologyContext.Topology[0]
+
+       for _, node := range topology.Node {
+               if node.UUID == searchedUUID {
+                       for _, name := range node.Name {
+                               if name.ValueName == "topology-node-name" {
+                                       return name.Value
+                               }
+                       }
+               }
+       }
+
+       return ""
+}
+
+func main() {
+       if len(os.Args) > 1 {
+               fmt.Printf("Parsing file %v...\n", os.Args[1])
+       } else {
+               fmt.Printf("Usage: %v <input>\nwhere input is the topology filename in JSON format.\n", os.Args[0])
+               os.Exit(0)
+       }
+
+       if _, err := os.Stat(os.Args[1]); errors.Is(err, os.ErrNotExist) {
+               fmt.Printf("File %v does not exist!\n", os.Args[1])
+               os.Exit(1)
+       }
+
+       topoJSONFile, err := os.Open(os.Args[1])
+       if err != nil {
+               fmt.Println(err)
+               os.Exit(1)
+       }
+       defer topoJSONFile.Close()
+
+       byteValue, _ := ioutil.ReadAll(topoJSONFile)
+
+       var topologyObject TapiContext
+       err = json.Unmarshal(byteValue, &topologyObject)
+       if err != nil {
+               fmt.Println(err)
+               os.Exit(1)
+       }
+
+       if len(topologyObject.TapiCommonContext.TapiTopologyTopologyContext.Topology) < 1 {
+               fmt.Println("Could not find TAPI Topology object in the loaded JSON!")
+               os.Exit(1)
+       }
+
+       createCommonParts()
+       createNetwork()
+       createServices(&topologyObject)
+
+       yamlData, err := yaml.Marshal(&configYAML)
+       if err != nil {
+               fmt.Println(err)
+       }
+
+       fileName := "docker-compose.yaml"
+       err = ioutil.WriteFile(fileName, yamlData, 0644)
+       if err != nil {
+               fmt.Println(err)
+       }
+
+       fmt.Println("File docker-compose.yaml created successfully!")
+}