openc3 7.0.0.pre.rc2 → 7.0.0
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.
- checksums.yaml +4 -4
- data/bin/openc3cli +13 -4
- data/bin/pipinstall +6 -7
- data/bin/pipuninstall +3 -5
- data/data/config/interface_modifiers.yaml +1 -1
- data/data/config/item_modifiers.yaml +18 -6
- data/data/config/telemetry.yaml +1 -1
- data/data/config/widgets.yaml +10 -0
- data/lib/openc3/accessors/json_accessor.rb +1 -1
- data/lib/openc3/api/cmd_api.rb +2 -0
- data/lib/openc3/api/settings_api.rb +2 -0
- data/lib/openc3/api/tlm_api.rb +3 -3
- data/lib/openc3/config/config_parser.rb +4 -4
- data/lib/openc3/conversions/conversion.rb +3 -3
- data/lib/openc3/core_ext/faraday.rb +4 -0
- data/lib/openc3/logs/log_writer.rb +24 -6
- data/lib/openc3/logs/packet_log_writer.rb +1 -4
- data/lib/openc3/logs/stream_log_pair.rb +11 -4
- data/lib/openc3/logs/text_log_writer.rb +1 -4
- data/lib/openc3/microservices/interface_microservice.rb +8 -2
- data/lib/openc3/microservices/log_microservice.rb +7 -2
- data/lib/openc3/microservices/microservice.rb +10 -4
- data/lib/openc3/microservices/queue_microservice.rb +9 -2
- data/lib/openc3/microservices/scope_cleanup_microservice.rb +116 -1
- data/lib/openc3/microservices/text_log_microservice.rb +4 -1
- data/lib/openc3/migrations/20241208080000_no_critical_cmd.rb +1 -1
- data/lib/openc3/migrations/20250402000000_periodic_only_default.rb +1 -1
- data/lib/openc3/migrations/20260203000000_remove_store_id.rb +28 -0
- data/lib/openc3/migrations/20260204000000_remove_decom_reducer.rb +29 -1
- data/lib/openc3/models/activity_model.rb +41 -9
- data/lib/openc3/models/auth_model.rb +54 -19
- data/lib/openc3/models/cvt_model.rb +2 -265
- data/lib/openc3/models/model.rb +16 -0
- data/lib/openc3/models/plugin_model.rb +18 -12
- data/lib/openc3/models/plugin_store_model.rb +1 -1
- data/lib/openc3/models/python_package_model.rb +2 -2
- data/lib/openc3/models/queue_model.rb +5 -3
- data/lib/openc3/models/script_engine_model.rb +1 -1
- data/lib/openc3/models/target_model.rb +75 -42
- data/lib/openc3/models/tool_config_model.rb +12 -0
- data/lib/openc3/models/tool_model.rb +18 -5
- data/lib/openc3/models/trigger_model.rb +1 -1
- data/lib/openc3/models/widget_model.rb +2 -9
- data/lib/openc3/operators/operator.rb +9 -7
- data/lib/openc3/packets/json_packet.rb +2 -0
- data/lib/openc3/packets/packet.rb +1 -0
- data/lib/openc3/packets/packet_config.rb +28 -12
- data/lib/openc3/script/calendar.rb +8 -0
- data/lib/openc3/script/script.rb +19 -0
- data/lib/openc3/script/storage.rb +6 -6
- data/lib/openc3/script/web_socket_api.rb +1 -1
- data/lib/openc3/system/system.rb +6 -6
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +0 -2
- data/lib/openc3/top_level.rb +15 -63
- data/lib/openc3/topics/command_topic.rb +1 -0
- data/lib/openc3/topics/limits_event_topic.rb +1 -1
- data/lib/openc3/utilities/authentication.rb +46 -7
- data/lib/openc3/utilities/authorization.rb +8 -1
- data/lib/openc3/utilities/aws_bucket.rb +2 -3
- data/lib/openc3/utilities/bucket_utilities.rb +3 -1
- data/lib/openc3/utilities/cli_generator.rb +7 -0
- data/lib/openc3/utilities/cmd_log.rb +1 -1
- data/lib/openc3/utilities/local_mode.rb +3 -0
- data/lib/openc3/utilities/process_manager.rb +1 -1
- data/lib/openc3/utilities/python_proxy.rb +11 -4
- data/lib/openc3/utilities/questdb_client.rb +764 -2
- data/lib/openc3/utilities/running_script.rb +25 -7
- data/lib/openc3/utilities/script.rb +452 -0
- data/lib/openc3/utilities/secrets.rb +1 -1
- data/lib/openc3/version.rb +5 -5
- data/templates/conversion/conversion.py +0 -8
- data/templates/conversion/conversion.rb +0 -11
- data/templates/tool_angular/package.json +2 -2
- data/templates/tool_react/package.json +1 -1
- data/templates/tool_svelte/package.json +1 -1
- data/templates/tool_vue/package.json +3 -3
- data/templates/widget/package.json +2 -2
- metadata +19 -19
- data/lib/openc3/migrations/20251022000000_remove_unique_id.rb +0 -23
- data/lib/openc3/migrations/20251213120000_reinstall_plugins.rb +0 -45
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0a06901f01bc9d8e7b6f0b123296da67475c08ea9cf50ef788a86b6da1308fcb
|
|
4
|
+
data.tar.gz: 34732b912cea1b4677f3e94ac0ba9f437e99217ccf54f9250816176ef5b63db1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5cda606ccb010606ad4b432685f53428cbf10b216f1cd06f2f55baac28fb723514dc3f8dfeadafc0958734237d3a7faf3f42439695481145914434e2a4bb1a58
|
|
7
|
+
data.tar.gz: 98532ea424c421554d45a6d155fadfc27e67ddf969a96be7653daebb30d5530dbb7601e13b5d3a3afa7dfd56718c161c060e81d67a5ee967a9248225554e1a03
|
data/bin/openc3cli
CHANGED
|
@@ -1348,12 +1348,21 @@ if not ARGV[0].nil? # argument(s) given
|
|
|
1348
1348
|
exit 0
|
|
1349
1349
|
end
|
|
1350
1350
|
client = OpenC3::Bucket.getClient()
|
|
1351
|
-
ENV.
|
|
1352
|
-
|
|
1353
|
-
|
|
1351
|
+
if ENV.fetch('OPENC3_CLOUD', 'local') == 'local'
|
|
1352
|
+
# In local mode we want to create all buckets to ensure they exist
|
|
1353
|
+
# Cloud deployments will have created buckets during provisioning
|
|
1354
|
+
# so we only need to ensure the correct policies and permissions are in place
|
|
1355
|
+
ENV.map do |key, value|
|
|
1356
|
+
if key.match(/^OPENC3_(.+)_BUCKET$/) && !value.empty?
|
|
1357
|
+
client.create(value)
|
|
1358
|
+
end
|
|
1354
1359
|
end
|
|
1355
1360
|
end
|
|
1356
|
-
|
|
1361
|
+
# Unless explicitly disabled, ensure the tools bucket is public
|
|
1362
|
+
unless ENV.fetch("OPENC3_NO_BUCKET_POLICY", false)
|
|
1363
|
+
client.ensure_public(ENV['OPENC3_TOOLS_BUCKET'])
|
|
1364
|
+
end
|
|
1365
|
+
# Always ensure the scriptrunner policy is in place since it is required for script execution
|
|
1357
1366
|
client.ensure_scriptrunner_policy(ENV['OPENC3_CONFIG_BUCKET'], ENV['OPENC3_LOGS_BUCKET'])
|
|
1358
1367
|
|
|
1359
1368
|
when 'runmigrations'
|
data/bin/pipinstall
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
pip3 install "$@"
|
|
2
|
+
uv venv "$PYTHONUSERBASE"
|
|
3
|
+
echo "uv pip install $@"
|
|
4
|
+
uv pip install --python "$PYTHONUSERBASE" "$@"
|
|
6
5
|
if [ $? -eq 0 ]; then
|
|
7
6
|
echo "Command succeeded"
|
|
8
7
|
else
|
|
9
8
|
echo "Command failed - retrying with --no-index"
|
|
10
|
-
|
|
11
|
-
if [ $? -
|
|
12
|
-
echo "ERROR:
|
|
9
|
+
uv pip install --python "$PYTHONUSERBASE" --no-index "$@"
|
|
10
|
+
if [ $? -ne 0 ]; then
|
|
11
|
+
echo "ERROR: uv pip install failed"
|
|
13
12
|
fi
|
|
14
13
|
fi
|
data/bin/pipuninstall
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
echo "pip3 uninstall $@"
|
|
5
|
-
pip3 uninstall "$@"
|
|
2
|
+
echo "uv pip uninstall $@"
|
|
3
|
+
uv pip uninstall --python "$PYTHONUSERBASE" "$@"
|
|
6
4
|
if [ $? -eq 0 ]; then
|
|
7
5
|
echo "Command succeeded"
|
|
8
6
|
else
|
|
9
|
-
echo "ERROR:
|
|
7
|
+
echo "ERROR: uv pip uninstall failed"
|
|
10
8
|
fi
|
|
@@ -53,7 +53,7 @@ RECONNECT_DELAY:
|
|
|
53
53
|
parameters:
|
|
54
54
|
- name: Delay
|
|
55
55
|
required: true
|
|
56
|
-
description: Delay in seconds between reconnect attempts. The default is
|
|
56
|
+
description: Delay in seconds between reconnect attempts. The default is 5 seconds.
|
|
57
57
|
values: ([0-9]*[.])?[0-9]+
|
|
58
58
|
DISABLE_DISCONNECT:
|
|
59
59
|
summary: Disable the Disconnect button on the Interfaces tab in the Server
|
|
@@ -72,7 +72,8 @@ GENERIC_READ_CONVERSION_START:
|
|
|
72
72
|
class (Note, referencing the packet as 'myself' is still supported for backwards
|
|
73
73
|
compatibility). The last line of code should return the converted
|
|
74
74
|
value. The GENERIC_READ_CONVERSION_END keyword specifies that all lines of
|
|
75
|
-
code for the conversion have been given.
|
|
75
|
+
code for the conversion have been given. To specify the bit size, type, and array size of the converted data,
|
|
76
|
+
use the CONVERTED_DATA keyword.
|
|
76
77
|
warning: Generic conversions are not a good long term solution. Consider creating
|
|
77
78
|
a conversion class and using READ_CONVERSION instead. READ_CONVERSION is easier
|
|
78
79
|
to debug and has higher performance.
|
|
@@ -81,22 +82,33 @@ GENERIC_READ_CONVERSION_START:
|
|
|
81
82
|
GENERIC_READ_CONVERSION_START
|
|
82
83
|
(value * 1.5).to_i # Convert the value by a scale factor
|
|
83
84
|
GENERIC_READ_CONVERSION_END
|
|
85
|
+
CONVERTED_DATA 32 UINT
|
|
84
86
|
python_example: |
|
|
85
87
|
APPEND_ITEM ITEM1 32 UINT
|
|
86
88
|
GENERIC_READ_CONVERSION_START
|
|
87
89
|
int(value * 1.5) # Convert the value by a scale factor
|
|
88
90
|
GENERIC_READ_CONVERSION_END
|
|
91
|
+
CONVERTED_DATA 32 UINT
|
|
92
|
+
GENERIC_READ_CONVERSION_END:
|
|
93
|
+
summary: Complete a generic read conversion
|
|
94
|
+
CONVERTED_DATA:
|
|
95
|
+
summary: Defines the bit size, type, and array size of the converted data for a read conversion
|
|
96
|
+
description: This keyword is used in conjunction with DERIVED items to specify the bit size, type, and array size of the converted data.
|
|
97
|
+
If this keyword is not used, DERIVED items are stored as strings in the decommutated data.
|
|
98
|
+
since: 7.0.0
|
|
89
99
|
parameters:
|
|
100
|
+
- name: Converted Bit Size
|
|
101
|
+
required: true
|
|
102
|
+
description: Bit size of converted value
|
|
103
|
+
values: \d+
|
|
90
104
|
- name: Converted Type
|
|
91
|
-
required:
|
|
105
|
+
required: true
|
|
92
106
|
description: Type of the converted value
|
|
93
107
|
values: <%= %w(INT UINT FLOAT STRING BLOCK) %>
|
|
94
|
-
- name: Converted
|
|
108
|
+
- name: Converted Array Size
|
|
95
109
|
required: false
|
|
96
|
-
description: Bit size of converted value
|
|
110
|
+
description: Bit size of the total array if the converted value is an array. Only specified if the converted type is an array.
|
|
97
111
|
values: \d+
|
|
98
|
-
GENERIC_READ_CONVERSION_END:
|
|
99
|
-
summary: Complete a generic read conversion
|
|
100
112
|
LIMITS:
|
|
101
113
|
summary: Defines a set of limits for a telemetry item
|
|
102
114
|
description: If limits are violated a message is printed in the Command and Telemetry Server
|
data/data/config/telemetry.yaml
CHANGED
data/data/config/widgets.yaml
CHANGED
|
@@ -894,6 +894,16 @@ Telemetry Widgets:
|
|
|
894
894
|
END
|
|
895
895
|
LIMITSCOLOR INST HEALTH_STATUS TEMP2 # Default is label with just item name
|
|
896
896
|
LIMITSCOLOR INST HEALTH_STATUS TEMP3 CONVERTED 20 TRUE # Full TGT/PKT/ITEM label
|
|
897
|
+
LIMITSCOLOR INST HEALTH_STATUS TEMP4
|
|
898
|
+
SETTING ASTRO TRUE
|
|
899
|
+
settings:
|
|
900
|
+
ASTRO:
|
|
901
|
+
summary: Display Astro status icons instead of a colored circle
|
|
902
|
+
description:
|
|
903
|
+
When set, the LIMITSCOLOR renders an Astro (rux-status) icon whose shape reflects
|
|
904
|
+
the severity level, improving accessibility for colorblind users.
|
|
905
|
+
Limits colors are automatically mapped to Astro statuses
|
|
906
|
+
(GREEN to normal, RED to critical, YELLOW to caution, BLUE to standby).
|
|
897
907
|
VALUELIMITSBAR:
|
|
898
908
|
summary: Displays an item VALUE followed by LIMITSBAR
|
|
899
909
|
parameters:
|
|
@@ -20,7 +20,7 @@ require 'openc3/accessors/accessor'
|
|
|
20
20
|
OpenC3.disable_warnings do
|
|
21
21
|
class JsonPath
|
|
22
22
|
def self.process_object(obj_or_str, opts = {})
|
|
23
|
-
obj_or_str.is_a?(String) ?
|
|
23
|
+
obj_or_str.is_a?(String) ? JSON.parse(obj_or_str, max_nesting: opts[:max_nesting], create_additions: true, allow_nan: true) : obj_or_str
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
end
|
data/lib/openc3/api/cmd_api.rb
CHANGED
|
@@ -73,6 +73,8 @@ module OpenC3
|
|
|
73
73
|
authorize(permission: 'admin', manual: manual, scope: scope, token: token)
|
|
74
74
|
SettingModel.set({ name: name, data: data }, scope: scope)
|
|
75
75
|
LocalMode.save_setting(scope, name, data)
|
|
76
|
+
username = user_info(token)['username'] || 'Anonymous'
|
|
77
|
+
Logger.info("User #{username} saved setting '#{name}': #{data}", scope: scope, user: username)
|
|
76
78
|
end
|
|
77
79
|
# save_setting is DEPRECATED
|
|
78
80
|
alias save_setting set_setting
|
data/lib/openc3/api/tlm_api.rb
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
require 'openc3/models/target_model'
|
|
25
25
|
require 'openc3/models/cvt_model'
|
|
26
|
-
require 'openc3/packets/packet'
|
|
26
|
+
# require 'openc3/packets/packet' # Circular require
|
|
27
27
|
require 'openc3/topics/telemetry_topic'
|
|
28
28
|
require 'openc3/topics/interface_topic'
|
|
29
29
|
require 'openc3/topics/decom_interface_topic'
|
|
@@ -281,7 +281,7 @@ module OpenC3
|
|
|
281
281
|
|
|
282
282
|
case value_type
|
|
283
283
|
when 'FORMATTED', 'WITH_UNITS'
|
|
284
|
-
if item['format_string']
|
|
284
|
+
if item['format_string'] or item['units']
|
|
285
285
|
results << [target_name, orig_packet_name, item_name, 'FORMATTED'].join('__')
|
|
286
286
|
# This logic must match the logic in Packet#decom
|
|
287
287
|
elsif item['states'] or (item['read_conversion'] and item['data_type'] != 'DERIVED')
|
|
@@ -304,7 +304,7 @@ module OpenC3
|
|
|
304
304
|
if item['limits']['DEFAULT']
|
|
305
305
|
results[-1] += '__LIMITS'
|
|
306
306
|
end
|
|
307
|
-
rescue RuntimeError
|
|
307
|
+
rescue RuntimeError
|
|
308
308
|
results << nil
|
|
309
309
|
end
|
|
310
310
|
end
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
# This file may also be used under the terms of a commercial license
|
|
16
16
|
# if purchased from OpenC3, Inc.
|
|
17
17
|
|
|
18
|
-
require 'openc3/top_level'
|
|
18
|
+
# require 'openc3/top_level' # Circular require
|
|
19
19
|
require 'openc3/ext/config_parser' if RUBY_ENGINE == 'ruby' and !ENV['OPENC3_NO_EXT']
|
|
20
20
|
require 'erb'
|
|
21
21
|
require 'fileutils'
|
|
22
|
+
require 'tempfile'
|
|
22
23
|
|
|
23
24
|
module OpenC3
|
|
24
25
|
# Reads OpenC3 style configuration data which consists of keywords followed
|
|
@@ -218,6 +219,7 @@ module OpenC3
|
|
|
218
219
|
&)
|
|
219
220
|
ensure
|
|
220
221
|
file.close unless file.closed?
|
|
222
|
+
file.unlink
|
|
221
223
|
end
|
|
222
224
|
end
|
|
223
225
|
|
|
@@ -417,9 +419,7 @@ module OpenC3
|
|
|
417
419
|
elsif copy.include?(':') # Check for Windows drive letter
|
|
418
420
|
copy = copy.split(':')[1]
|
|
419
421
|
end
|
|
420
|
-
|
|
421
|
-
FileUtils.mkdir_p(File.dirname(parsed_filename)) # Create the path
|
|
422
|
-
file = File.open(parsed_filename, 'w+')
|
|
422
|
+
file = Tempfile.new(copy)
|
|
423
423
|
file.puts output
|
|
424
424
|
file.rewind # Rewind so the file is ready to read
|
|
425
425
|
file
|
|
@@ -20,11 +20,11 @@ module OpenC3
|
|
|
20
20
|
class Conversion
|
|
21
21
|
# @return [Symbol] The converted data type. Must be one of
|
|
22
22
|
# {OpenC3::StructureItem#data_type}
|
|
23
|
-
|
|
23
|
+
attr_accessor :converted_type
|
|
24
24
|
# @return [Integer] The size in bits of the converted value
|
|
25
|
-
|
|
25
|
+
attr_accessor :converted_bit_size
|
|
26
26
|
# @return [Integer] The size in bits of the converted array value
|
|
27
|
-
|
|
27
|
+
attr_accessor :converted_array_size
|
|
28
28
|
# @return [Array] The arguments passed to the conversion
|
|
29
29
|
attr_reader :params
|
|
30
30
|
|
|
@@ -126,6 +126,7 @@ module OpenC3
|
|
|
126
126
|
@cleanup_times = []
|
|
127
127
|
@previous_time_nsec_since_epoch = nil
|
|
128
128
|
@tmp_dir = Dir.mktmpdir
|
|
129
|
+
@wait_threads = []
|
|
129
130
|
|
|
130
131
|
# This is an optimization to avoid creating a new entry object
|
|
131
132
|
# each time we create an entry which we do a LOT!
|
|
@@ -154,9 +155,8 @@ module OpenC3
|
|
|
154
155
|
|
|
155
156
|
# Stops all logging and closes the current log file.
|
|
156
157
|
def stop
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return threads
|
|
158
|
+
@mutex.synchronize { close_file(false); @logging_enabled = false; }
|
|
159
|
+
return @wait_threads
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
# Stop all logging, close the current log file, and kill the logging threads.
|
|
@@ -173,6 +173,13 @@ module OpenC3
|
|
|
173
173
|
return threads
|
|
174
174
|
end
|
|
175
175
|
|
|
176
|
+
def cleanup
|
|
177
|
+
if @tmp_dir
|
|
178
|
+
FileUtils.remove_entry_secure(@tmp_dir, true)
|
|
179
|
+
@tmp_dir = nil
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
176
183
|
def graceful_kill
|
|
177
184
|
@cancel_threads = true
|
|
178
185
|
end
|
|
@@ -307,8 +314,19 @@ module OpenC3
|
|
|
307
314
|
# to keep a full file's worth of data in the stream. This is what prevents continuous stream growth.
|
|
308
315
|
# Returns thread that moves log to bucket
|
|
309
316
|
def close_file(take_mutex = true)
|
|
310
|
-
threads = []
|
|
311
317
|
@mutex.lock if take_mutex
|
|
318
|
+
|
|
319
|
+
# Remove old wait_threads
|
|
320
|
+
to_remove = []
|
|
321
|
+
@wait_threads.each do |thread|
|
|
322
|
+
unless thread.alive?
|
|
323
|
+
to_remove << thread
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
to_remove.each do |thread|
|
|
327
|
+
@wait_threads.delete(thread)
|
|
328
|
+
end
|
|
329
|
+
|
|
312
330
|
begin
|
|
313
331
|
if @file
|
|
314
332
|
begin
|
|
@@ -322,7 +340,7 @@ module OpenC3
|
|
|
322
340
|
# Cleanup timestamps here so they are unset for the next file
|
|
323
341
|
@first_time = nil
|
|
324
342
|
@last_time = nil
|
|
325
|
-
|
|
343
|
+
@wait_threads << BucketUtilities.move_log_file_to_bucket(@filename, bucket_key)
|
|
326
344
|
# Now that the file is in storage, trim the Redis stream after a delay
|
|
327
345
|
@cleanup_offsets << {}
|
|
328
346
|
@last_offsets.each do |redis_topic, last_offset|
|
|
@@ -342,7 +360,7 @@ module OpenC3
|
|
|
342
360
|
ensure
|
|
343
361
|
@mutex.unlock if take_mutex
|
|
344
362
|
end
|
|
345
|
-
return
|
|
363
|
+
return @wait_threads
|
|
346
364
|
end
|
|
347
365
|
|
|
348
366
|
def bucket_filename
|
|
@@ -137,7 +137,6 @@ module OpenC3
|
|
|
137
137
|
# Closing a log file isn't critical so we just log an error
|
|
138
138
|
# Returns threads that moves log to bucket
|
|
139
139
|
def close_file(take_mutex = true)
|
|
140
|
-
threads = []
|
|
141
140
|
@mutex.lock if take_mutex
|
|
142
141
|
begin
|
|
143
142
|
# Need to write the OFFSET_MARKER for each packet
|
|
@@ -145,12 +144,10 @@ module OpenC3
|
|
|
145
144
|
write_entry(:OFFSET_MARKER, nil, nil, nil, nil, nil, last_offset + ',' + redis_topic, nil) if @file
|
|
146
145
|
end
|
|
147
146
|
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
return super(false)
|
|
150
148
|
ensure
|
|
151
149
|
@mutex.unlock if take_mutex
|
|
152
150
|
end
|
|
153
|
-
return threads
|
|
154
151
|
end
|
|
155
152
|
|
|
156
153
|
def get_packet_index(cmd_or_tlm, target_name, packet_name, entry_type, data)
|
|
@@ -43,13 +43,20 @@ module OpenC3
|
|
|
43
43
|
|
|
44
44
|
# Close any open stream log files
|
|
45
45
|
def stop
|
|
46
|
-
@read_log.stop
|
|
47
|
-
@write_log.stop
|
|
46
|
+
threads = @read_log.stop
|
|
47
|
+
threads.concat(@write_log.stop)
|
|
48
|
+
return threads
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
def shutdown
|
|
51
|
-
@read_log.shutdown
|
|
52
|
-
@write_log.shutdown
|
|
52
|
+
threads = @read_log.shutdown
|
|
53
|
+
threads.concat(@write_log.shutdown)
|
|
54
|
+
return threads
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def cleanup
|
|
58
|
+
@read_log.cleanup
|
|
59
|
+
@write_log.cleanup
|
|
53
60
|
end
|
|
54
61
|
|
|
55
62
|
# Clone the stream log pair
|
|
@@ -68,7 +68,6 @@ module OpenC3
|
|
|
68
68
|
# Closing a log file isn't critical so we just log an error
|
|
69
69
|
# Returns threads that moves log to bucket
|
|
70
70
|
def close_file(take_mutex = true)
|
|
71
|
-
threads = []
|
|
72
71
|
@mutex.lock if take_mutex
|
|
73
72
|
begin
|
|
74
73
|
# Need to write the OFFSET_MARKER for each packet
|
|
@@ -79,12 +78,10 @@ module OpenC3
|
|
|
79
78
|
write_entry(time.to_nsec_from_epoch, data.as_json(allow_nan: true).to_json(allow_nan: true)) if @file
|
|
80
79
|
end
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
return super(false)
|
|
84
82
|
ensure
|
|
85
83
|
@mutex.unlock if take_mutex
|
|
86
84
|
end
|
|
87
|
-
return threads
|
|
88
85
|
end
|
|
89
86
|
|
|
90
87
|
def extension
|
|
@@ -779,7 +779,6 @@ module OpenC3
|
|
|
779
779
|
else
|
|
780
780
|
@logger.error "#{@interface.name}: #{connect_error.formatted}"
|
|
781
781
|
unless @connection_failed_messages.include?(connect_error.message)
|
|
782
|
-
OpenC3.write_exception_file(connect_error)
|
|
783
782
|
@connection_failed_messages << connect_error.message
|
|
784
783
|
end
|
|
785
784
|
end
|
|
@@ -800,7 +799,6 @@ module OpenC3
|
|
|
800
799
|
else
|
|
801
800
|
@logger.error "#{@interface.name}: #{err.formatted}"
|
|
802
801
|
unless @connection_lost_messages.include?(err.message)
|
|
803
|
-
OpenC3.write_exception_file(err)
|
|
804
802
|
@connection_lost_messages << err.message
|
|
805
803
|
end
|
|
806
804
|
end
|
|
@@ -888,6 +886,14 @@ module OpenC3
|
|
|
888
886
|
def shutdown(_sig = nil)
|
|
889
887
|
@logger.info "#{@interface ? @interface.name : @name}: shutdown requested"
|
|
890
888
|
stop()
|
|
889
|
+
if @interface and @interface.stream_log_pair
|
|
890
|
+
threads = @interface.stream_log_pair.shutdown
|
|
891
|
+
# Wait for all the logging threads to move files to buckets
|
|
892
|
+
threads.flatten.compact.each do |thread|
|
|
893
|
+
thread.join
|
|
894
|
+
end
|
|
895
|
+
@interface.stream_log_pair.cleanup
|
|
896
|
+
end
|
|
891
897
|
super()
|
|
892
898
|
end
|
|
893
899
|
|
|
@@ -125,8 +125,8 @@ module OpenC3
|
|
|
125
125
|
def shutdown
|
|
126
126
|
# Make sure all the existing logs are properly closed down
|
|
127
127
|
threads = []
|
|
128
|
-
@plws.each do |
|
|
129
|
-
plw_hash.each do |
|
|
128
|
+
@plws.each do |_target_name, plw_hash|
|
|
129
|
+
plw_hash.each do |_type, plw|
|
|
130
130
|
threads.concat(plw.shutdown)
|
|
131
131
|
end
|
|
132
132
|
end
|
|
@@ -134,6 +134,11 @@ module OpenC3
|
|
|
134
134
|
threads.flatten.compact.each do |thread|
|
|
135
135
|
thread.join
|
|
136
136
|
end
|
|
137
|
+
@plws.each do |_target_name, plw_hash|
|
|
138
|
+
plw_hash.each do |_type, plw|
|
|
139
|
+
plw.cleanup
|
|
140
|
+
end
|
|
141
|
+
end
|
|
137
142
|
super()
|
|
138
143
|
end
|
|
139
144
|
end
|
|
@@ -88,6 +88,7 @@ module OpenC3
|
|
|
88
88
|
@name = name
|
|
89
89
|
split_name = name.split("__")
|
|
90
90
|
raise "Name #{name} doesn't match convention of SCOPE__TYPE__NAME" if split_name.length != 3
|
|
91
|
+
microservice_type = split_name[1].to_s.upcase
|
|
91
92
|
|
|
92
93
|
@scope = split_name[0]
|
|
93
94
|
$openc3_scope = @scope
|
|
@@ -102,8 +103,14 @@ module OpenC3
|
|
|
102
103
|
|
|
103
104
|
OpenC3.setup_open_telemetry(@name, false)
|
|
104
105
|
|
|
106
|
+
@temp_dir = OpenC3.sanitize_path(File.join(Dir.tmpdir, @name))
|
|
107
|
+
|
|
105
108
|
# Create temp folder for this microservice
|
|
106
|
-
|
|
109
|
+
# This will already have been setup by plugin_microservice.rb if USER
|
|
110
|
+
if is_plugin or microservice_type != 'USER'
|
|
111
|
+
FileUtils.remove_entry_secure(@temp_dir, true)
|
|
112
|
+
Dir.mkdir(@temp_dir)
|
|
113
|
+
end
|
|
107
114
|
|
|
108
115
|
# Get microservice configuration from Redis
|
|
109
116
|
@config = MicroserviceModel.get(name: @name, scope: @scope)
|
|
@@ -142,14 +149,13 @@ module OpenC3
|
|
|
142
149
|
cmd_array = @config["cmd"]
|
|
143
150
|
|
|
144
151
|
# Get Microservice files from bucket storage
|
|
145
|
-
temp_dir = Dir.mktmpdir
|
|
146
152
|
bucket = ENV['OPENC3_CONFIG_BUCKET']
|
|
147
153
|
client = Bucket.getClient()
|
|
148
154
|
|
|
149
155
|
prefix = "#{@scope}/microservices/#{@name}/"
|
|
150
156
|
file_count = 0
|
|
151
157
|
client.list_objects(bucket: bucket, prefix: prefix).each do |object|
|
|
152
|
-
response_target = File.join(temp_dir, object.key.split(prefix)[-1])
|
|
158
|
+
response_target = OpenC3.sanitize_path(File.join(@temp_dir, object.key.split(prefix)[-1]))
|
|
153
159
|
FileUtils.mkdir_p(File.dirname(response_target))
|
|
154
160
|
client.get_object(bucket: bucket, key: object.key, path: response_target)
|
|
155
161
|
file_count += 1
|
|
@@ -157,7 +163,7 @@ module OpenC3
|
|
|
157
163
|
|
|
158
164
|
# Adjust @work_dir to microservice files downloaded if files and a relative path
|
|
159
165
|
if file_count > 0 and @work_dir[0] != '/'
|
|
160
|
-
@work_dir = File.join(temp_dir, @work_dir)
|
|
166
|
+
@work_dir = OpenC3.sanitize_path(File.join(@temp_dir, @work_dir))
|
|
161
167
|
end
|
|
162
168
|
|
|
163
169
|
# Check Syntax on any ruby files
|
|
@@ -18,6 +18,8 @@ require 'openc3/utilities/authentication'
|
|
|
18
18
|
require 'openc3/api/api'
|
|
19
19
|
|
|
20
20
|
module OpenC3
|
|
21
|
+
saved_verbose = $VERBOSE
|
|
22
|
+
$VERBOSE = false
|
|
21
23
|
module Script
|
|
22
24
|
private
|
|
23
25
|
# Override the prompt_for_hazardous method to always return true since there is no user to prompt
|
|
@@ -25,6 +27,7 @@ module OpenC3
|
|
|
25
27
|
return true
|
|
26
28
|
end
|
|
27
29
|
end
|
|
30
|
+
$VERBOSE = saved_verbose
|
|
28
31
|
|
|
29
32
|
# The queue processor runs in a single thread and processes commands via cmd_api.
|
|
30
33
|
class QueueProcessor
|
|
@@ -71,10 +74,14 @@ module OpenC3
|
|
|
71
74
|
else
|
|
72
75
|
cmd_params = {}
|
|
73
76
|
end
|
|
74
|
-
|
|
77
|
+
validate = command.key?('validate') ? command['validate'] : true
|
|
78
|
+
timeout = command['timeout']
|
|
79
|
+
cmd(command['target_name'], command['cmd_name'], cmd_params, queue: false, validate: validate, timeout: timeout, scope: @scope)
|
|
75
80
|
elsif command['value']
|
|
76
81
|
# Legacy format: use single string parameter for backwards compatibility
|
|
77
|
-
|
|
82
|
+
validate = command.key?('validate') ? command['validate'] : true
|
|
83
|
+
timeout = command['timeout']
|
|
84
|
+
cmd(command['value'], queue: false, validate: validate, timeout: timeout, scope: @scope)
|
|
78
85
|
else
|
|
79
86
|
@logger.error "QueueProcessor: Invalid command format, missing required fields"
|
|
80
87
|
end
|