1 /************************************************************************
2 * Copyright 2022 highstreet technologies GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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 ************************************************************************/
26 "github.com/goccy/go-yaml"
31 // common parts consist of the anchors that are reused for the services
32 func createCommonParts() {
33 configYAML.Version = "3.8"
35 configYAML.CommonEnvs = make(map[string]string, 1)
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}"
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"
65 configYAML.RuEnv = make(map[string]string, 1)
66 configYAML.RuEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate netconf-call-home web-cut-through"
68 configYAML.TopoEnv = make(map[string]string, 1)
69 configYAML.TopoEnv["NTS_NF_STANDALONE_START_FEATURES"] = "datastore-populate netconf-call-home web-cut-through"
72 commonNf.StopGracePeriod = "5m"
73 commonNf.CapAdd = append(commonNf.CapAdd, "SYS_ADMIN")
74 commonNf.CapAdd = append(commonNf.CapAdd, "SYS_PTRACE")
75 configYAML.CommonNfs = commonNf
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"]
83 defaultNetwork.External = make(map[string]string, 1)
84 defaultNetwork.External["name"] = "oam"
86 configYAML.Networks["default"] = defaultNetwork
89 // creates an O-RU simulator instance as a service
90 func addORUasService(name string) {
91 service := configYAML.Services[name]
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
97 commonEnv := &CommonEnv{}
99 env := &Env{commonEnv, nil, ruEnv, nil}
100 service.Environment = *env
102 configYAML.Services[name] = service
105 // creates an O-DU simulator instance as a service
106 func addODUasService(name string) {
107 service := configYAML.Services[name]
109 service.Image = "${NEXUS3_DOCKER_REPO}nts-ng-o-ran-du:${NTS_BUILD_VERSION}"
110 service.ContainerName = "ntsim-ng-" + name
111 service.Hostname = name
113 commonEnv := &CommonEnv{}
115 env := &Env{commonEnv, duEnv, nil, nil}
116 service.Environment = *env
118 configYAML.Services[name] = service
121 // iterates through the topology and creates associated services
122 func createServices(topologyJSON *TapiContext) {
123 topology := topologyJSON.TapiCommonContext.TapiTopologyTopologyContext.Topology[0]
125 configYAML.Services = make(map[string]Service, 1)
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)
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]
142 for _, node := range topology.Node {
143 if node.UUID == nodeUUID {
144 return node.ORanScTopologyFunction
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]
155 for _, node := range topology.Node {
156 if node.UUID == searchedUUID {
157 for _, name := range node.Name {
158 if name.ValueName == "topology-node-name" {
169 if len(os.Args) > 1 {
170 fmt.Printf("Parsing file %v...\n", os.Args[1])
172 fmt.Printf("Usage: %v <input>\nwhere input is the topology filename in JSON format.\n", os.Args[0])
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])
181 topoJSONFile, err := os.Open(os.Args[1])
186 defer topoJSONFile.Close()
188 byteValue, _ := ioutil.ReadAll(topoJSONFile)
190 var topologyObject TapiContext
191 err = json.Unmarshal(byteValue, &topologyObject)
197 if len(topologyObject.TapiCommonContext.TapiTopologyTopologyContext.Topology) < 1 {
198 fmt.Println("Could not find TAPI Topology object in the loaded JSON!")
204 createServices(&topologyObject)
206 yamlData, err := yaml.Marshal(&configYAML)
211 fileName := "docker-compose.yaml"
212 err = ioutil.WriteFile(fileName, yamlData, 0644)
217 fmt.Println("File docker-compose.yaml created successfully!")