Add to_directory method to relevant object classes
[oam.git] / code / network-generator / network_generation / model / python / o_ran_smo.py
1 # Copyright 2023 highstreet technologies GmbH
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # !/usr/bin/python
16
17 """
18 A Class representing an O-RAN Service Management and
19 Orchestration Framework (SMO)
20 """
21 import xml.etree.ElementTree as ET
22 from typing import Any, cast
23
24 import network_generation.model.python.hexagon as Hexagon
25 from network_generation.model.python.geo_location import GeoLocation
26 from network_generation.model.python.hexagon import Hex
27 from network_generation.model.python.o_ran_near_rt_ric import ORanNearRtRic
28 from network_generation.model.python.o_ran_node import (
29     IORanNode,
30     ORanNode,
31     default_value,
32 )
33 from network_generation.model.python.o_ran_termination_point import (
34     ORanTerminationPoint,
35 )
36 from network_generation.model.python.tower import Tower
37
38 # Define the "IORanSmo" interface
39 IORanSmo = IORanNode
40
41
42 # Define an abstract O-RAN Node class
43 class ORanSmo(ORanNode):
44     """
45     Class representing an O-RAN Service Management and Operation object.
46     """
47
48     def __init__(
49         self,
50         data: dict[str, Any] = cast(dict[str, Any], default_value),
51         **kwargs: dict[str, Any]
52     ) -> None:
53         o_ran_smo_data: IORanSmo = self._to_o_ran_smo_data(data)
54         super().__init__(cast(dict[str, Any], o_ran_smo_data), **kwargs)
55         if self.parent is not None:
56             self._o_ran_near_rt_rics: list[
57                 ORanNearRtRic
58             ] = self._calculate_near_rt_rics()
59
60     def _calculate_near_rt_rics(self) -> list[ORanNearRtRic]:
61         hex_ring_radius: int = (
62             self.parent.spiral_radius_profile.oRanSmoSpiralRadiusOfNearRtRics
63             if self.parent is not None
64             else 1
65         )
66         hex_list: list[
67             Hex
68         ] = self.parent.spiral_radius_profile.oRanNearRtRicSpiral(
69             self.position, hex_ring_radius
70         )
71         result: list[ORanNearRtRic] = []
72         for index, hex in enumerate(hex_list):
73             s: str = "00" + str(index)
74             name: str = "-".join(
75                 [self.name.replace("SMO", "NearRtRic"), s[len(s) - 2: len(s)]]
76             )
77             network_center: GeoLocation = self.parent.center
78             newGeo = Hexagon.hex_to_geo_location(
79                 self.layout, hex, network_center
80             ).json()
81             result.append(
82                 ORanNearRtRic(
83                     {
84                         "name": name,
85                         "geoLocation": newGeo,
86                         "position": hex,
87                         "layout": self.layout,
88                         "parent": self,
89                     },
90                 )
91             )
92         return result
93
94     def _to_o_ran_smo_data(self, data: dict[str, Any]) -> IORanSmo:
95         result: IORanSmo = default_value
96         for key, key_type in IORanSmo.__annotations__.items():
97             if key in data:
98                 result[key] = data[key]  # type: ignore
99         return result
100
101     @property
102     def o_ran_near_rt_rics(self) -> list[ORanNearRtRic]:
103         return self._o_ran_near_rt_rics
104
105     @property
106     def towers(self) -> list[Tower]:
107         result: list[Tower] = []
108         for ric in self.o_ran_near_rt_rics:
109             for tower in ric.towers:
110                 result.append(tower)
111         return result
112
113     # @property
114     def termination_points(self) -> list[ORanTerminationPoint]:
115         result: list[ORanTerminationPoint] = super().termination_points()
116         phy_tp: str = "-".join([self.name, "phy".upper()])
117         result.append(ORanTerminationPoint({"id": phy_tp, "name": phy_tp}))
118         for interface in ["a1", "o1", "o2"]:
119             id: str = "-".join([self.name, interface.upper()])
120             result.append(
121                 ORanTerminationPoint(
122                     {
123                         "id": id,
124                         "name": id,
125                         "supporter": phy_tp,
126                         "parent": self,
127                     },
128                 )
129             )
130         return result
131
132     def to_topology_nodes(self) -> list[dict[str, Any]]:
133         result: list[dict[str, Any]] = super().to_topology_nodes()
134         for ric in self.o_ran_near_rt_rics:
135             result.extend(ric.to_topology_nodes())
136         return result
137
138     def to_topology_links(self) -> list[dict[str, Any]]:
139         result: list[dict[str, Any]] = []  # super().to_topology_links()
140         for ric in self.o_ran_near_rt_rics:
141             result.extend(ric.to_topology_links())
142         return result
143
144     def toKml(self) -> ET.Element:
145         smo: ET.Element = ET.Element("Folder")
146         open: ET.Element = ET.SubElement(smo, "open")
147         open.text = "1"
148         name: ET.Element = ET.SubElement(smo, "name")
149         name.text = self.name
150         for ric in self.o_ran_near_rt_rics:
151             smo.append(ric.toKml())
152         return smo
153
154     def toSvg(self) -> ET.Element:
155         return ET.Element("not-implemented-yet-TODO")
156
157     def to_directory(self, parent_dir: str) -> None:
158         for ric in self.o_ran_near_rt_rics:
159             ric.to_directory(parent_dir)