blob: 6fdbf38ec696a306c70d2cb64d63c3ec90ef313e [file] [log] [blame]
/************************************************************************
* 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!")
}