nost-tools 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nost-tools might be problematic. Click here for more details.
- nost_tools/__init__.py +29 -0
- nost_tools/application.py +793 -0
- nost_tools/application_utils.py +262 -0
- nost_tools/configuration.py +304 -0
- nost_tools/entity.py +73 -0
- nost_tools/errors.py +14 -0
- nost_tools/logger_application.py +192 -0
- nost_tools/managed_application.py +261 -0
- nost_tools/manager.py +472 -0
- nost_tools/observer.py +181 -0
- nost_tools/publisher.py +141 -0
- nost_tools/schemas.py +426 -0
- nost_tools/simulator.py +531 -0
- nost_tools-2.0.0.dist-info/METADATA +119 -0
- nost_tools-2.0.0.dist-info/RECORD +18 -0
- nost_tools-2.0.0.dist-info/WHEEL +5 -0
- nost_tools-2.0.0.dist-info/licenses/LICENSE +29 -0
- nost_tools-2.0.0.dist-info/top_level.txt +1 -0
nost_tools/publisher.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provides utility classes to help applications bind behavior to temporal events.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from datetime import datetime, timedelta
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from .observer import Observer
|
|
10
|
+
from .simulator import Mode, Simulator
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .application import Application
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ScenarioTimeIntervalPublisher(Observer, ABC):
|
|
17
|
+
"""
|
|
18
|
+
Publishes messages at a regular interval (scenario time).
|
|
19
|
+
|
|
20
|
+
Provides the simulation with time status messages, also refered to as 'heartbeat messages',
|
|
21
|
+
or 'simulation time statuses'.
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
app (:obj:`Application`): application to publish messages
|
|
25
|
+
time_status_step (:obj:`timedelta`): scenario duration between time status messages
|
|
26
|
+
time_status_init (:obj:`datetime`): scenario time for first time status message
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
app: "Application",
|
|
32
|
+
time_status_step: timedelta = None,
|
|
33
|
+
time_status_init: datetime = None,
|
|
34
|
+
):
|
|
35
|
+
"""
|
|
36
|
+
Initializes a new scenario time interval publisher.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
app (:obj:`Application`): application to publish messages
|
|
40
|
+
time_status_step (:obj:`timedelta`): scenario duration between time status messages
|
|
41
|
+
time_status_init (:obj:`datetime`): scenario time for first time status message
|
|
42
|
+
"""
|
|
43
|
+
self.app = app
|
|
44
|
+
self.time_status_step = time_status_step
|
|
45
|
+
self.time_status_init = time_status_init
|
|
46
|
+
self._next_time_status = None
|
|
47
|
+
# TODO: consider adding the `publish_message` callable as an argument rather than abstract method
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def publish_message(self) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Publishes a message.
|
|
53
|
+
"""
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
def on_change(
|
|
57
|
+
self, source: object, property_name: str, old_value: object, new_value: object
|
|
58
|
+
) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Publishes a message after a designated interval of scenario time.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
source (object): observable that triggered the change
|
|
64
|
+
property_name (str): name of the changed property
|
|
65
|
+
old_value (obj): old value of the named property
|
|
66
|
+
new_value (obj): new value of the named property
|
|
67
|
+
"""
|
|
68
|
+
if property_name == Simulator.PROPERTY_MODE and new_value == Mode.INITIALIZED:
|
|
69
|
+
if self.time_status_init is None:
|
|
70
|
+
self._next_time_status = self.app.simulator.get_init_time()
|
|
71
|
+
else:
|
|
72
|
+
self._next_time_status = self.time_status_init
|
|
73
|
+
elif property_name == Simulator.PROPERTY_TIME:
|
|
74
|
+
while self._next_time_status <= new_value:
|
|
75
|
+
self.publish_message()
|
|
76
|
+
if self.time_status_step is None:
|
|
77
|
+
self._next_time_status += self.app.simulator.get_time_step()
|
|
78
|
+
else:
|
|
79
|
+
self._next_time_status += self.time_status_step
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class WallclockTimeIntervalPublisher(Observer, ABC):
|
|
83
|
+
"""
|
|
84
|
+
Publishes messages at a regular interval (wallclock time).
|
|
85
|
+
|
|
86
|
+
Attributes:
|
|
87
|
+
app (:obj:`Application`): application to publish messages
|
|
88
|
+
time_status_step (:obj:`timedelta`): wallclock duration between time status messages
|
|
89
|
+
time_status_init (:obj:`datetime`): wallclock time for first time status message
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
def __init__(
|
|
93
|
+
self,
|
|
94
|
+
app: "Application",
|
|
95
|
+
time_status_step: timedelta = None,
|
|
96
|
+
time_status_init: datetime = None,
|
|
97
|
+
):
|
|
98
|
+
"""
|
|
99
|
+
Initializes a new wallclock time interval publisher.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
app (:obj:`Application`): application to publish messages
|
|
103
|
+
time_status_step (:obj:`timedelta`): wallclock duration between time status messages
|
|
104
|
+
time_status_init (:obj:`datetime`): wallclock time for first time status message
|
|
105
|
+
"""
|
|
106
|
+
self.app = app
|
|
107
|
+
self.time_status_step = time_status_step
|
|
108
|
+
self.time_status_init = time_status_init
|
|
109
|
+
self._next_time_status = None
|
|
110
|
+
|
|
111
|
+
@abstractmethod
|
|
112
|
+
def publish_message(self) -> None:
|
|
113
|
+
"""
|
|
114
|
+
Publishes a message.
|
|
115
|
+
"""
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
def on_change(self, source, property_name, old_value, new_value):
|
|
119
|
+
"""
|
|
120
|
+
Publishes a message after a designated interval of scenario time.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
source (object): observable that triggered the change
|
|
124
|
+
property_name (str): name of the changed property
|
|
125
|
+
old_value (obj): old value of the named property
|
|
126
|
+
new_value (obj): new value of the named property
|
|
127
|
+
"""
|
|
128
|
+
if property_name == Simulator.PROPERTY_MODE and new_value == Mode.INITIALIZED:
|
|
129
|
+
if self.time_status_init is None:
|
|
130
|
+
self._next_time_status = self.app.simulator.get_wallclock_time()
|
|
131
|
+
else:
|
|
132
|
+
self._next_time_status = self.time_status_init
|
|
133
|
+
elif property_name == Simulator.PROPERTY_TIME:
|
|
134
|
+
while self._next_time_status <= self.app.simulator.get_wallclock_time():
|
|
135
|
+
self.publish_message()
|
|
136
|
+
if self.time_status_step is None:
|
|
137
|
+
self._next_time_status += (
|
|
138
|
+
self.app.simulator.get_wallclock_time_step()
|
|
139
|
+
)
|
|
140
|
+
else:
|
|
141
|
+
self._next_time_status += self.time_status_step
|
nost_tools/schemas.py
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provides object models for common data structures.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime, timedelta
|
|
6
|
+
from typing import Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field, model_validator
|
|
9
|
+
|
|
10
|
+
from .simulator import Mode
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InitTaskingParameters(BaseModel):
|
|
14
|
+
"""
|
|
15
|
+
Tasking parameters to initialize an execution.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
sim_start_time: datetime = Field(
|
|
19
|
+
..., description="Earliest possible scenario start time.", alias="simStartTime"
|
|
20
|
+
)
|
|
21
|
+
sim_stop_time: datetime = Field(
|
|
22
|
+
..., description="Latest possible scenario end time.", alias="simStopTime"
|
|
23
|
+
)
|
|
24
|
+
required_apps: List[str] = Field(
|
|
25
|
+
[], description="List of required applications.", alias="requiredApps"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class InitCommand(BaseModel):
|
|
30
|
+
"""
|
|
31
|
+
Command message to initialize an execution.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
tasking_parameters: InitTaskingParameters = Field(
|
|
35
|
+
...,
|
|
36
|
+
description="Tasking parameters for the initialize command.",
|
|
37
|
+
alias="taskingParameters",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class StartTaskingParameters(BaseModel):
|
|
42
|
+
"""
|
|
43
|
+
Tasking parameters to start an execution.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
start_time: Optional[datetime] = Field(
|
|
47
|
+
None,
|
|
48
|
+
description="Wallclock time at which to start execution.",
|
|
49
|
+
alias="startTime",
|
|
50
|
+
)
|
|
51
|
+
sim_start_time: Optional[datetime] = Field(
|
|
52
|
+
None,
|
|
53
|
+
description="Scenario time at which to start execution.",
|
|
54
|
+
alias="simStartTime",
|
|
55
|
+
)
|
|
56
|
+
sim_stop_time: Optional[datetime] = Field(
|
|
57
|
+
None,
|
|
58
|
+
description="Scenario time at which to stop execution.",
|
|
59
|
+
alias="simStopTime",
|
|
60
|
+
)
|
|
61
|
+
time_scaling_factor: float = Field(
|
|
62
|
+
1.0,
|
|
63
|
+
gt=0,
|
|
64
|
+
description="Scenario seconds per wallclock second.",
|
|
65
|
+
alias="timeScalingFactor",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class StartCommand(BaseModel):
|
|
70
|
+
"""
|
|
71
|
+
Command message to start an execution.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
tasking_parameters: StartTaskingParameters = Field(
|
|
75
|
+
...,
|
|
76
|
+
description="Tasking parameters for the start command.",
|
|
77
|
+
alias="taskingParameters",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class StopTaskingParameters(BaseModel):
|
|
82
|
+
"""
|
|
83
|
+
Tasking parameters to stop an execution.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
sim_stop_time: datetime = Field(
|
|
87
|
+
...,
|
|
88
|
+
description="Scenario time at which to stop execution.",
|
|
89
|
+
alias="simStopTime",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class StopCommand(BaseModel):
|
|
94
|
+
"""
|
|
95
|
+
Command message to stop an execution.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
tasking_parameters: StopTaskingParameters = Field(
|
|
99
|
+
...,
|
|
100
|
+
description="Tasking parameters for the stop command.",
|
|
101
|
+
alias="taskingParameters",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class UpdateTaskingParameters(BaseModel):
|
|
106
|
+
"""
|
|
107
|
+
Tasking parameters to update an execution.
|
|
108
|
+
"""
|
|
109
|
+
|
|
110
|
+
time_scaling_factor: float = Field(
|
|
111
|
+
...,
|
|
112
|
+
gt=0,
|
|
113
|
+
description="Time scaling factor (scenario seconds per wallclock second).",
|
|
114
|
+
alias="timeScalingFactor",
|
|
115
|
+
)
|
|
116
|
+
sim_update_time: datetime = Field(
|
|
117
|
+
...,
|
|
118
|
+
description="Scenario time at which to update the time scaling factor.",
|
|
119
|
+
alias="simUpdateTime",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class UpdateCommand(BaseModel):
|
|
124
|
+
"""
|
|
125
|
+
Command message to update an execution.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
tasking_parameters: UpdateTaskingParameters = Field(
|
|
129
|
+
...,
|
|
130
|
+
description="Tasking parameters for the stop command.",
|
|
131
|
+
alias="taskingParameters",
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class TimeStatusProperties(BaseModel):
|
|
136
|
+
"""
|
|
137
|
+
Properties to report time status.
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
sim_time: datetime = Field(
|
|
141
|
+
..., description="Current scenario time.", alias="simTime"
|
|
142
|
+
)
|
|
143
|
+
time: datetime = Field(..., description="Current wallclock time.")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class TimeStatus(BaseModel):
|
|
147
|
+
"""
|
|
148
|
+
Message to report time status.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
name: str = Field(
|
|
152
|
+
..., description="Name of the application providing a time status."
|
|
153
|
+
)
|
|
154
|
+
description: Optional[str] = Field(
|
|
155
|
+
None, description="Description of the application providing a ready status."
|
|
156
|
+
)
|
|
157
|
+
properties: TimeStatusProperties = Field(
|
|
158
|
+
..., description="Properties for the time status."
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class ModeStatusProperties(BaseModel):
|
|
163
|
+
"""
|
|
164
|
+
Properties to report mode status.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
mode: Mode = Field(..., description="Current execution mode.")
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class ModeStatus(BaseModel):
|
|
171
|
+
"""
|
|
172
|
+
Message to report mode status.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
name: str = Field(
|
|
176
|
+
..., description="Name of the application providing a mode status."
|
|
177
|
+
)
|
|
178
|
+
description: Optional[str] = Field(
|
|
179
|
+
None, description="Description of the application providing a ready status."
|
|
180
|
+
)
|
|
181
|
+
properties: ModeStatusProperties = Field(
|
|
182
|
+
..., description="Properties for the mode status."
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ReadyStatusProperties(BaseModel):
|
|
187
|
+
"""
|
|
188
|
+
Properties to report ready status.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
ready: bool = Field(True, description="True, if this application is ready.")
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class ReadyStatus(BaseModel):
|
|
195
|
+
"""
|
|
196
|
+
Message to report ready status.
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
name: str = Field(
|
|
200
|
+
..., description="Name of the application providing a ready status."
|
|
201
|
+
)
|
|
202
|
+
description: Optional[str] = Field(
|
|
203
|
+
None, description="Description of the application providing a ready status."
|
|
204
|
+
)
|
|
205
|
+
properties: ReadyStatusProperties = Field(
|
|
206
|
+
..., description="Properties for the ready status."
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class InfoConfig(BaseModel):
|
|
211
|
+
title: Optional[str] = Field(None, description="Title of the simulation.")
|
|
212
|
+
version: Optional[str] = Field(None, description="Version of the simulation.")
|
|
213
|
+
description: Optional[str] = Field(
|
|
214
|
+
None, description="Description of the simulation."
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class RabbitMQConfig(BaseModel):
|
|
219
|
+
keycloak_authentication: bool = Field(
|
|
220
|
+
False, description="Keycloak authentication for RabbitMQ."
|
|
221
|
+
)
|
|
222
|
+
host: str = Field("localhost", description="RabbitMQ host.")
|
|
223
|
+
port: int = Field(5672, description="RabbitMQ port.")
|
|
224
|
+
tls: bool = Field(False, description="RabbitMQ TLS/SSL.")
|
|
225
|
+
virtual_host: str = Field("/", description="RabbitMQ virtual host.")
|
|
226
|
+
message_expiration: str = Field(
|
|
227
|
+
"60000", description="RabbitMQ expiration, in milliseconds."
|
|
228
|
+
)
|
|
229
|
+
delivery_mode: int = Field(
|
|
230
|
+
2, description="RabbitMQ delivery mode (1: non-persistent, 2: durable)."
|
|
231
|
+
)
|
|
232
|
+
content_type: str = Field(
|
|
233
|
+
"text/plain",
|
|
234
|
+
description="RabbitMQ MIME content type (application/json, text/plain, etc.).",
|
|
235
|
+
)
|
|
236
|
+
heartbeat: int = Field(30, description="RabbitMQ heartbeat interval, in seconds.")
|
|
237
|
+
connection_attempts: int = Field(
|
|
238
|
+
3, description="RabbitMQ connection attempts before giving up."
|
|
239
|
+
)
|
|
240
|
+
retry_delay: int = Field(5, description="RabbitMQ retry delay, in seconds.")
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class KeycloakConfig(BaseModel):
|
|
244
|
+
host: str = Field("localhost", description="Keycloak host.")
|
|
245
|
+
port: int = Field(8080, description="Keycloak port.")
|
|
246
|
+
realm: str = Field("master", description="Keycloak realm.")
|
|
247
|
+
tls: bool = Field(False, description="Keycloak TLS/SSL.")
|
|
248
|
+
token_refresh_interval: int = Field(
|
|
249
|
+
60, description="Keycloak token refresh interval, in seconds."
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class ServersConfig(BaseModel):
|
|
254
|
+
rabbitmq: RabbitMQConfig = Field(..., description="RabbitMQ configuration.")
|
|
255
|
+
keycloak: KeycloakConfig = Field(..., description="Keycloak configuration.")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class GeneralConfig(BaseModel):
|
|
259
|
+
prefix: str = Field("nost", description="Execution prefix.")
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class ManagerConfig(BaseModel):
|
|
263
|
+
sim_start_time: Optional[datetime] = Field(
|
|
264
|
+
None, description="Simulation start time."
|
|
265
|
+
)
|
|
266
|
+
sim_stop_time: Optional[datetime] = Field(None, description="Simulation stop time.")
|
|
267
|
+
start_time: Optional[datetime] = Field(None, description="Execution start time.")
|
|
268
|
+
time_step: timedelta = Field(
|
|
269
|
+
timedelta(seconds=1),
|
|
270
|
+
description="Time step for the simulation.",
|
|
271
|
+
)
|
|
272
|
+
time_scale_factor: float = Field(1.0, description="Time scale factor.")
|
|
273
|
+
time_scale_updates: List[str] = Field(
|
|
274
|
+
default_factory=list, description="List of time scale updates."
|
|
275
|
+
)
|
|
276
|
+
time_status_step: Optional[timedelta] = Field(None, description="Time status step.")
|
|
277
|
+
time_status_init: Optional[datetime] = Field(None, description="Time status init.")
|
|
278
|
+
command_lead: timedelta = Field(
|
|
279
|
+
timedelta(seconds=0), description="Command lead time."
|
|
280
|
+
)
|
|
281
|
+
required_apps: List[str] = Field(
|
|
282
|
+
default_factory=list, description="List of required applications."
|
|
283
|
+
)
|
|
284
|
+
init_retry_delay_s: int = Field(5, description="Initial retry delay in seconds.")
|
|
285
|
+
init_max_retry: int = Field(5, description="Initial maximum retry attempts.")
|
|
286
|
+
set_offset: bool = Field(True, description="Set offset.")
|
|
287
|
+
shut_down_when_terminated: bool = Field(
|
|
288
|
+
False, description="Shut down when terminated."
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
@model_validator(mode="before")
|
|
292
|
+
def scale_time(cls, values):
|
|
293
|
+
time_scale_factor = values.get("time_scale_factor", 1.0)
|
|
294
|
+
|
|
295
|
+
if "time_status_step" in values:
|
|
296
|
+
time_status_step = values["time_status_step"]
|
|
297
|
+
if isinstance(time_status_step, str):
|
|
298
|
+
time_status_step = timedelta(
|
|
299
|
+
seconds=float(time_status_step.split(":")[-1])
|
|
300
|
+
)
|
|
301
|
+
if isinstance(time_status_step, timedelta):
|
|
302
|
+
values["time_status_step"] = timedelta(
|
|
303
|
+
seconds=time_status_step.total_seconds() * time_scale_factor
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
return values
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class ManagedApplicationConfig(BaseModel):
|
|
310
|
+
time_scale_factor: float = Field(1.0, description="Time scale factor.")
|
|
311
|
+
time_step: timedelta = Field(
|
|
312
|
+
timedelta(seconds=1), description="Time step for swe_change."
|
|
313
|
+
)
|
|
314
|
+
set_offset: bool = Field(True, description="Set offset.")
|
|
315
|
+
time_status_step: timedelta = Field(None, description="Time status step.")
|
|
316
|
+
time_status_init: datetime = Field(None, description="Time status init.")
|
|
317
|
+
shut_down_when_terminated: bool = Field(
|
|
318
|
+
False, description="Shut down when terminated."
|
|
319
|
+
)
|
|
320
|
+
manager_app_name: str = Field("manager", description="Manager application name.")
|
|
321
|
+
|
|
322
|
+
@model_validator(mode="before")
|
|
323
|
+
def scale_time(cls, values):
|
|
324
|
+
time_scale_factor = values.get("time_scale_factor", 1.0)
|
|
325
|
+
|
|
326
|
+
if "time_step" in values:
|
|
327
|
+
time_step = values["time_step"]
|
|
328
|
+
if isinstance(time_step, str):
|
|
329
|
+
time_step = timedelta(seconds=float(time_step.split(":")[-1]))
|
|
330
|
+
if isinstance(time_step, timedelta):
|
|
331
|
+
values["time_step"] = timedelta(
|
|
332
|
+
seconds=time_step.total_seconds() * time_scale_factor
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
if "time_status_step" in values:
|
|
336
|
+
time_status_step = values["time_status_step"]
|
|
337
|
+
if isinstance(time_status_step, str):
|
|
338
|
+
time_status_step = timedelta(
|
|
339
|
+
seconds=float(time_status_step.split(":")[-1])
|
|
340
|
+
)
|
|
341
|
+
if isinstance(time_status_step, timedelta):
|
|
342
|
+
values["time_status_step"] = timedelta(
|
|
343
|
+
seconds=time_status_step.total_seconds() * time_scale_factor
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
return values
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class LoggerApplicationConfig(BaseModel):
|
|
350
|
+
set_offset: Optional[bool] = Field(True, description="Set offset.")
|
|
351
|
+
time_scale_factor: Optional[float] = Field(1.0, description="Time scale factor.")
|
|
352
|
+
time_step: Optional[timedelta] = Field(
|
|
353
|
+
timedelta(seconds=1), description="Time step for swe_change."
|
|
354
|
+
)
|
|
355
|
+
time_status_step: Optional[timedelta] = Field(
|
|
356
|
+
timedelta(seconds=10), description="Time status step."
|
|
357
|
+
)
|
|
358
|
+
time_status_init: Optional[datetime] = Field(
|
|
359
|
+
datetime(2019, 3, 1, 0, 0, 0), description="Time status init."
|
|
360
|
+
)
|
|
361
|
+
shut_down_when_terminated: Optional[bool] = Field(
|
|
362
|
+
False, description="Shut down when terminated."
|
|
363
|
+
)
|
|
364
|
+
manager_app_name: Optional[str] = Field(
|
|
365
|
+
"manager", description="Manager application name."
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
class ExecConfig(BaseModel):
|
|
370
|
+
general: GeneralConfig
|
|
371
|
+
manager: ManagerConfig
|
|
372
|
+
managed_application: ManagedApplicationConfig
|
|
373
|
+
logger_application: LoggerApplicationConfig
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
class Config(BaseModel):
|
|
377
|
+
servers: ServersConfig = Field(..., description="Servers configuration.")
|
|
378
|
+
channels: Dict[str, Dict] = Field({}, description="Channels configuration.")
|
|
379
|
+
execution: ExecConfig = Field(..., description="Applications configuration.")
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class ExchangeConfig(BaseModel):
|
|
383
|
+
name: str
|
|
384
|
+
type: str = "topic"
|
|
385
|
+
durable: bool = True
|
|
386
|
+
auto_delete: bool = False
|
|
387
|
+
vhost: str = "/"
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
class ChannelConfig(BaseModel):
|
|
391
|
+
app: str
|
|
392
|
+
address: str
|
|
393
|
+
exchange: str
|
|
394
|
+
durable: bool
|
|
395
|
+
auto_delete: bool
|
|
396
|
+
vhost: str
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
class Credentials(BaseModel):
|
|
400
|
+
username: str = Field(..., description="Username for authentication.")
|
|
401
|
+
password: str = Field(..., description="Password for authentication.")
|
|
402
|
+
client_id: Optional[str] = Field("", description="Client ID for authentication.")
|
|
403
|
+
client_secret_key: Optional[str] = Field(
|
|
404
|
+
"", description="Client secret key for authentication."
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
class SimulationConfig(BaseModel):
|
|
409
|
+
exchanges: Dict[str, Dict] = Field(
|
|
410
|
+
default_factory=dict, description="Dictionary of exchanges."
|
|
411
|
+
)
|
|
412
|
+
queues: List[Dict] = Field(default_factory=list, description="List of channels.")
|
|
413
|
+
execution_parameters: ExecConfig = Field(..., description="Execution parameters.")
|
|
414
|
+
predefined_exchanges_queues: bool = Field(
|
|
415
|
+
False, description="Predefined exchanges and queues."
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
class RuntimeConfig(BaseModel):
|
|
420
|
+
credentials: Credentials = Field(..., description="Credentials for authentication.")
|
|
421
|
+
server_configuration: Config = (
|
|
422
|
+
Field(..., description="Simulation configuration."),
|
|
423
|
+
)
|
|
424
|
+
simulation_configuration: SimulationConfig = Field(
|
|
425
|
+
..., description="Simulation configuration."
|
|
426
|
+
)
|