Merge "ADD N1, N2 N3 interfacing to topology generation"
[oam.git] / code / network-topology-parser / main.go
1 /************************************************************************
2 * Copyright 2022 highstreet technologies GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ************************************************************************/
16
17 package main
18
19 import (
20         "encoding/json"
21         "errors"
22         "fmt"
23         "io/ioutil"
24         "os"
25
26         "github.com/goccy/go-yaml"
27 )
28
29 var configYAML Config
30
31 // common parts consist of the anchors that are reused for the services
32 func createCommonParts() {
33         configYAML.Version = "3.8"
34
35         configYAML.CommonEnvs = make(map[string]string, 1)
36
37         configYAML.CommonEnvs["IPv6_ENABLED"] = "${IPv6_ENABLED}"
38         configYAML.CommonEnvs["SSH_CONNECTIONS"] = "${SSH_CONNECTIONS}"
39         configYAML.CommonEnvs["TLS_CONNECTIONS"] = "${TLS_CONNECTIONS}"
40         configYAML.CommonEnvs["NTS_NF_MOUNT_POINT_ADDRESSING_METHOD"] = "${NTS_NF_MOUNT_POINT_ADDRESSING_METHOD}"
41         configYAML.CommonEnvs["NTS_HOST_IP"] = "${NTS_HOST_IP}"
42         configYAML.CommonEnvs["NTS_HOST_BASE_PORT"] = "${NTS_HOST_BASE_PORT}"
43         configYAML.CommonEnvs["NTS_HOST_NETCONF_SSH_BASE_PORT"] = "${NTS_HOST_NETCONF_SSH_BASE_PORT}"
44         configYAML.CommonEnvs["NTS_HOST_NETCONF_TLS_BASE_PORT"] = "${NTS_HOST_NETCONF_TLS_BASE_PORT}"
45         configYAML.CommonEnvs["NTS_HOST_TRANSFER_FTP_BASE_PORT"] = "${NTS_HOST_TRANSFER_FTP_BASE_PORT}"
46         configYAML.CommonEnvs["NTS_HOST_TRANSFER_SFTP_BASE_PORT"] = "${NTS_HOST_TRANSFER_SFTP_BASE_PORT}"
47         configYAML.CommonEnvs["SDN_CONTROLLER_PROTOCOL"] = "${SDN_CONTROLLER_PROTOCOL}"
48         configYAML.CommonEnvs["SDN_CONTROLLER_IP"] = "${SDNC_OAM_IPv6}"
49         configYAML.CommonEnvs["SDN_CONTROLLER_PORT"] = "${SDNC_REST_PORT}"
50         configYAML.CommonEnvs["SDN_CONTROLLER_CALLHOME_IP"] = "${SDNC_OAM_IPv6}"
51         configYAML.CommonEnvs["SDN_CONTROLLER_CALLHOME_PORT"] = "${SDN_CONTROLLER_CALLHOME_PORT}"
52         configYAML.CommonEnvs["SDN_CONTROLLER_USERNAME"] = "${ADMIN_USERNAME}"
53         configYAML.CommonEnvs["SDN_CONTROLLER_PASSWORD"] = "${ADMIN_PASSWORD}"
54         configYAML.CommonEnvs["VES_COMMON_HEADER_VERSION"] = "${VES_COMMON_HEADER_VERSION}"
55         configYAML.CommonEnvs["VES_ENDPOINT_PROTOCOL"] = "${VES_ENDPOINT_PROTOCOL}"
56         configYAML.CommonEnvs["VES_ENDPOINT_IP"] = "${VES_COLLECTOR_OAM_IPv6}"
57         configYAML.CommonEnvs["VES_ENDPOINT_PORT"] = "${VES_ENDPOINT_PORT}"
58         configYAML.CommonEnvs["VES_ENDPOINT_AUTH_METHOD"] = "${VES_ENDPOINT_AUTH_METHOD}"
59         configYAML.CommonEnvs["VES_ENDPOINT_USERNAME"] = "${VES_ENDPOINT_USERNAME}"
60         configYAML.CommonEnvs["VES_ENDPOINT_PASSWORD"] = "${VES_ENDPOINT_PASSWORD}"
61
62         configYAML.DuEnv = make(map[string]string, 1)
63         configYAML.DuEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate ves-heartbeat ves-file-ready ves-pnf-registration web-cut-through"
64
65         configYAML.RuEnv = make(map[string]string, 1)
66         configYAML.RuEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate netconf-call-home web-cut-through"
67
68         configYAML.TopoEnv = make(map[string]string, 1)
69         configYAML.TopoEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate netconf-call-home web-cut-through"
70
71         var commonNf CommonNf
72         commonNf.StopGracePeriod = "5m"
73         commonNf.CapAdd = append(commonNf.CapAdd, "SYS_ADMIN")
74         commonNf.CapAdd = append(commonNf.CapAdd, "SYS_PTRACE")
75         configYAML.CommonNfs = commonNf
76 }
77
78 // creates the network information to be used by the services
79 func createNetwork() {
80         configYAML.Networks = make(map[string]Network, 1)
81         defaultNetwork := configYAML.Networks["default"]
82
83         defaultNetwork.External = make(map[string]string, 1)
84         defaultNetwork.External["name"] = "oam"
85
86         configYAML.Networks["default"] = defaultNetwork
87 }
88
89 // creates an O-RU simulator instance as a service
90 func addORUasService(name string) {
91         service := configYAML.Services[name]
92
93         service.Image = "${NEXUS3_DOCKER_REPO}nts-ng-o-ran-ru-fh:${NTS_BUILD_VERSION}"
94         service.ContainerName = "ntsim-ng-" + name
95         service.Hostname = name
96
97         commonEnv := &CommonEnv{}
98         ruEnv := &RuEnv{}
99         env := &Env{commonEnv, nil, ruEnv, nil}
100         service.Environment = *env
101
102         configYAML.Services[name] = service
103 }
104
105 // creates an O-DU simulator instance as a service
106 func addODUasService(name string) {
107         service := configYAML.Services[name]
108
109         service.Image = "${NEXUS3_DOCKER_REPO}nts-ng-o-ran-du:${NTS_BUILD_VERSION}"
110         service.ContainerName = "ntsim-ng-" + name
111         service.Hostname = name
112
113         commonEnv := &CommonEnv{}
114         duEnv := &DuEnv{}
115         env := &Env{commonEnv, duEnv, nil, nil}
116         service.Environment = *env
117
118         configYAML.Services[name] = service
119 }
120
121 // iterates through the topology and creates associated services
122 func createServices(topologyJSON *TapiContext) {
123         topology := topologyJSON.TapiCommonContext.TapiTopologyTopologyContext.Topology[0]
124
125         configYAML.Services = make(map[string]Service, 1)
126
127         for _, node := range topology.Node {
128                 if node.ORanScTopologyFunction == "o-ran-sc-topology-common:o-ru" {
129                         name := getNodeNameFromUUID(node.UUID, topologyJSON)
130                         addORUasService(name)
131                 } else if node.ORanScTopologyFunction == "o-ran-sc-topology-common:o-du" {
132                         name := getNodeNameFromUUID(node.UUID, topologyJSON)
133                         addODUasService(name)
134                 }
135         }
136 }
137
138 // returns the type of O-RAN-SC Topology Function of the input TAPI Node
139 func getTypeOfNodeUUID(nodeUUID string, topologyJSON *TapiContext) string {
140         topology := topologyJSON.TapiCommonContext.TapiTopologyTopologyContext.Topology[0]
141
142         for _, node := range topology.Node {
143                 if node.UUID == nodeUUID {
144                         return node.ORanScTopologyFunction
145                 }
146         }
147
148         return ""
149 }
150
151 // returns the Node Name of the TAPI Node with the input UUID
152 func getNodeNameFromUUID(searchedUUID string, topologyJSON *TapiContext) string {
153         topology := topologyJSON.TapiCommonContext.TapiTopologyTopologyContext.Topology[0]
154
155         for _, node := range topology.Node {
156                 if node.UUID == searchedUUID {
157                         for _, name := range node.Name {
158                                 if name.ValueName == "topology-node-name" {
159                                         return name.Value
160                                 }
161                         }
162                 }
163         }
164
165         return ""
166 }
167
168 func main() {
169         if len(os.Args) > 1 {
170                 fmt.Printf("Parsing file %v...\n", os.Args[1])
171         } else {
172                 fmt.Printf("Usage: %v <input>\nwhere input is the topology filename in JSON format.\n", os.Args[0])
173                 os.Exit(0)
174         }
175
176         if _, err := os.Stat(os.Args[1]); errors.Is(err, os.ErrNotExist) {
177                 fmt.Printf("File %v does not exist!\n", os.Args[1])
178                 os.Exit(1)
179         }
180
181         topoJSONFile, err := os.Open(os.Args[1])
182         if err != nil {
183                 fmt.Println(err)
184                 os.Exit(1)
185         }
186         defer topoJSONFile.Close()
187
188         byteValue, _ := ioutil.ReadAll(topoJSONFile)
189
190         var topologyObject TapiContext
191         err = json.Unmarshal(byteValue, &topologyObject)
192         if err != nil {
193                 fmt.Println(err)
194                 os.Exit(1)
195         }
196
197         if len(topologyObject.TapiCommonContext.TapiTopologyTopologyContext.Topology) < 1 {
198                 fmt.Println("Could not find TAPI Topology object in the loaded JSON!")
199                 os.Exit(1)
200         }
201
202         createCommonParts()
203         createNetwork()
204         createServices(&topologyObject)
205
206         yamlData, err := yaml.Marshal(&configYAML)
207         if err != nil {
208                 fmt.Println(err)
209         }
210
211         fileName := "docker-compose.yaml"
212         err = ioutil.WriteFile(fileName, yamlData, 0644)
213         if err != nil {
214                 fmt.Println(err)
215         }
216
217         fmt.Println("File docker-compose.yaml created successfully!")
218 }