openc3 5.17.1 → 5.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -4
- data/bin/cstol_converter +14 -14
- data/bin/openc3cli +190 -8
- data/data/config/_interfaces.yaml +5 -5
- data/data/config/command_modifiers.yaml +59 -0
- data/data/config/interface_modifiers.yaml +19 -9
- data/data/config/item_modifiers.yaml +34 -26
- data/data/config/microservice.yaml +4 -1
- data/data/config/param_item_modifiers.yaml +17 -1
- data/data/config/parameter_modifiers.yaml +30 -13
- data/data/config/plugins.yaml +9 -5
- data/data/config/screen.yaml +9 -9
- data/data/config/table_manager.yaml +2 -2
- data/data/config/telemetry_modifiers.yaml +9 -4
- data/data/config/tool.yaml +4 -1
- data/data/config/widgets.yaml +44 -17
- data/ext/openc3/ext/config_parser/config_parser.c +1 -1
- data/ext/openc3/ext/packet/packet.c +7 -1
- data/ext/openc3/ext/platform/platform.c +3 -3
- data/ext/openc3/ext/structure/structure.c +56 -76
- data/lib/openc3/accessors/accessor.rb +1 -0
- data/lib/openc3/accessors/binary_accessor.rb +174 -15
- data/lib/openc3/accessors/form_accessor.rb +2 -2
- data/lib/openc3/accessors/http_accessor.rb +1 -1
- data/lib/openc3/accessors/json_accessor.rb +6 -4
- data/lib/openc3/accessors/template_accessor.rb +6 -9
- data/lib/openc3/accessors/xml_accessor.rb +1 -1
- data/lib/openc3/api/cmd_api.rb +72 -44
- data/lib/openc3/api/config_api.rb +10 -10
- data/lib/openc3/api/interface_api.rb +28 -21
- data/lib/openc3/api/limits_api.rb +30 -30
- data/lib/openc3/api/metrics_api.rb +3 -3
- data/lib/openc3/api/offline_access_api.rb +5 -5
- data/lib/openc3/api/router_api.rb +25 -19
- data/lib/openc3/api/settings_api.rb +10 -10
- data/lib/openc3/api/stash_api.rb +10 -10
- data/lib/openc3/api/target_api.rb +10 -10
- data/lib/openc3/api/tlm_api.rb +44 -44
- data/lib/openc3/config/config_parser.rb +1 -1
- data/lib/openc3/conversions/bit_reverse_conversion.rb +60 -0
- data/lib/openc3/conversions/ip_read_conversion.rb +59 -0
- data/lib/openc3/conversions/ip_write_conversion.rb +61 -0
- data/lib/openc3/conversions/object_read_conversion.rb +88 -0
- data/lib/openc3/conversions/object_write_conversion.rb +38 -0
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +7 -7
- data/lib/openc3/conversions.rb +6 -1
- data/lib/openc3/core_ext/array.rb +5 -5
- data/lib/openc3/core_ext/exception.rb +9 -2
- data/lib/openc3/core_ext/string.rb +2 -2
- data/lib/openc3/interfaces/http_server_interface.rb +1 -0
- data/lib/openc3/interfaces/interface.rb +1 -1
- data/lib/openc3/interfaces/linc_interface.rb +3 -3
- data/lib/openc3/io/json_api.rb +11 -6
- data/lib/openc3/io/json_drb.rb +19 -21
- data/lib/openc3/io/json_rpc.rb +15 -14
- data/lib/openc3/logs/buffered_packet_log_writer.rb +3 -3
- data/lib/openc3/logs/log_writer.rb +7 -8
- data/lib/openc3/logs/packet_log_writer.rb +7 -7
- data/lib/openc3/logs/text_log_writer.rb +4 -4
- data/lib/openc3/microservices/decom_microservice.rb +19 -4
- data/lib/openc3/microservices/interface_microservice.rb +41 -3
- data/lib/openc3/microservices/microservice.rb +11 -11
- data/lib/openc3/microservices/reaction_microservice.rb +2 -2
- data/lib/openc3/microservices/scope_cleanup_microservice.rb +1 -1
- data/lib/openc3/microservices/timeline_microservice.rb +70 -45
- data/lib/openc3/microservices/trigger_group_microservice.rb +3 -3
- data/lib/openc3/migrations/20240915000000_activity_uuid.rb +28 -0
- data/lib/openc3/models/activity_model.rb +124 -92
- data/lib/openc3/models/auth_model.rb +31 -2
- data/lib/openc3/models/cvt_model.rb +11 -5
- data/lib/openc3/models/gem_model.rb +8 -8
- data/lib/openc3/models/plugin_model.rb +3 -3
- data/lib/openc3/models/reducer_model.rb +2 -2
- data/lib/openc3/models/scope_model.rb +45 -14
- data/lib/openc3/models/sorted_model.rb +5 -5
- data/lib/openc3/models/target_model.rb +7 -4
- data/lib/openc3/models/tool_config_model.rb +1 -1
- data/lib/openc3/models/tool_model.rb +4 -4
- data/lib/openc3/models/widget_model.rb +11 -5
- data/lib/openc3/operators/microservice_operator.rb +2 -2
- data/lib/openc3/operators/operator.rb +14 -12
- data/lib/openc3/packets/command_validator.rb +48 -0
- data/lib/openc3/packets/commands.rb +6 -14
- data/lib/openc3/packets/packet.rb +49 -16
- data/lib/openc3/packets/packet_config.rb +47 -25
- data/lib/openc3/packets/packet_item.rb +5 -0
- data/lib/openc3/packets/parsers/packet_parser.rb +3 -3
- data/lib/openc3/packets/structure.rb +87 -15
- data/lib/openc3/packets/structure_item.rb +76 -53
- data/lib/openc3/packets/telemetry.rb +6 -27
- data/lib/openc3/script/api_shared.rb +7 -5
- data/lib/openc3/script/calendar.rb +2 -2
- data/lib/openc3/script/commands.rb +6 -4
- data/lib/openc3/script/extract.rb +5 -3
- data/lib/openc3/script/metadata.rb +2 -2
- data/lib/openc3/script/suite.rb +17 -17
- data/lib/openc3/script/web_socket_api.rb +11 -0
- data/lib/openc3/streams/serial_stream.rb +2 -3
- data/lib/openc3/streams/stream.rb +2 -2
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +10 -10
- data/lib/openc3/tools/table_manager/table_manager_core.rb +11 -11
- data/lib/openc3/tools/table_manager/table_parser.rb +2 -3
- data/lib/openc3/topics/command_decom_topic.rb +2 -1
- data/lib/openc3/topics/command_topic.rb +3 -3
- data/lib/openc3/topics/decom_interface_topic.rb +4 -3
- data/lib/openc3/topics/system_events_topic.rb +40 -0
- data/lib/openc3/topics/telemetry_decom_topic.rb +1 -1
- data/lib/openc3/utilities/authentication.rb +2 -1
- data/lib/openc3/utilities/authorization.rb +4 -3
- data/lib/openc3/utilities/cli_generator.rb +15 -8
- data/lib/openc3/utilities/cosmos_rails_formatter.rb +60 -0
- data/lib/openc3/utilities/crc.rb +6 -6
- data/lib/openc3/utilities/local_mode.rb +2 -1
- data/lib/openc3/utilities/logger.rb +44 -34
- data/lib/openc3/utilities/metric.rb +1 -2
- data/lib/openc3/utilities/quaternion.rb +18 -18
- data/lib/openc3/utilities/target_file.rb +4 -4
- data/lib/openc3/version.rb +6 -6
- data/lib/openc3/win32/win32_main.rb +2 -2
- data/templates/tool_angular/package.json +22 -22
- data/templates/tool_react/package.json +13 -13
- data/templates/tool_svelte/package.json +14 -14
- data/templates/tool_svelte/src/services/openc3-api.js +17 -17
- data/templates/tool_vue/package.json +13 -13
- data/templates/widget/package.json +11 -12
- data/templates/widget/src/Widget.vue +0 -1
- metadata +25 -2
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2024, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -26,6 +26,18 @@ require 'openc3/models/plugin_model'
|
|
26
26
|
require 'openc3/models/microservice_model'
|
27
27
|
require 'openc3/models/setting_model'
|
28
28
|
require 'openc3/models/trigger_group_model'
|
29
|
+
require 'openc3/topics/system_events_topic'
|
30
|
+
|
31
|
+
begin
|
32
|
+
require 'openc3-enterprise/models/cmd_authority_model'
|
33
|
+
rescue LoadError
|
34
|
+
# Stub out the Enterprise CmdAuthorityModel to do nothing
|
35
|
+
class CmdAuthorityModel
|
36
|
+
def self.names(scope:)
|
37
|
+
[]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
29
41
|
|
30
42
|
module OpenC3
|
31
43
|
class ScopeModel < Model
|
@@ -37,9 +49,13 @@ module OpenC3
|
|
37
49
|
attr_accessor :text_log_retain_time
|
38
50
|
attr_accessor :tool_log_retain_time
|
39
51
|
attr_accessor :cleanup_poll_time
|
52
|
+
attr_accessor :command_authority
|
40
53
|
|
41
54
|
# NOTE: The following three class methods are used by the ModelController
|
42
55
|
# and are reimplemented to enable various Model class methods to work
|
56
|
+
#
|
57
|
+
# The scope keyword is given to support the ModelController method signature
|
58
|
+
# even though it is not used
|
43
59
|
def self.get(name:, scope: nil)
|
44
60
|
super(PRIMARY_KEY, name: name)
|
45
61
|
end
|
@@ -52,13 +68,13 @@ module OpenC3
|
|
52
68
|
super(PRIMARY_KEY)
|
53
69
|
end
|
54
70
|
|
55
|
-
def self.from_json(json
|
71
|
+
def self.from_json(json)
|
56
72
|
json = JSON.parse(json, :allow_nan => true, :create_additions => true) if String === json
|
57
73
|
raise "json data is nil" if json.nil?
|
58
|
-
self.new(**json.transform_keys(&:to_sym)
|
74
|
+
self.new(**json.transform_keys(&:to_sym))
|
59
75
|
end
|
60
76
|
|
61
|
-
def self.get_model(name
|
77
|
+
def self.get_model(name:)
|
62
78
|
json = get(name: name)
|
63
79
|
if json
|
64
80
|
return from_json(json)
|
@@ -73,18 +89,15 @@ module OpenC3
|
|
73
89
|
text_log_retain_time: nil,
|
74
90
|
tool_log_retain_time: nil,
|
75
91
|
cleanup_poll_time: 900,
|
76
|
-
|
77
|
-
|
92
|
+
command_authority: false,
|
93
|
+
updated_at: nil
|
78
94
|
)
|
79
95
|
super(
|
80
96
|
PRIMARY_KEY,
|
81
97
|
name: name,
|
82
|
-
text_log_cycle_time: text_log_cycle_time,
|
83
|
-
text_log_cycle_size: text_log_cycle_size,
|
84
|
-
text_log_retain_time: text_log_retain_time,
|
85
|
-
tool_log_retain_time: tool_log_retain_time,
|
86
|
-
cleanup_poll_time: cleanup_poll_time,
|
87
98
|
updated_at: updated_at,
|
99
|
+
# This sets the @scope variable which is sort of redundant for the ScopeModel
|
100
|
+
# (since its the same as @name) but every model has a @scope
|
88
101
|
scope: name
|
89
102
|
)
|
90
103
|
@text_log_cycle_time = text_log_cycle_time
|
@@ -92,21 +105,34 @@ module OpenC3
|
|
92
105
|
@text_log_retain_time = text_log_retain_time
|
93
106
|
@tool_log_retain_time = tool_log_retain_time
|
94
107
|
@cleanup_poll_time = cleanup_poll_time
|
108
|
+
@command_authority = command_authority
|
95
109
|
@children = []
|
96
110
|
end
|
97
111
|
|
98
112
|
def create(update: false, force: false, queued: false)
|
99
|
-
# Ensure there are no "." in the scope name - prevents gems
|
113
|
+
# Ensure there are no "." in the scope name - prevents gems accidentally becoming scope names
|
100
114
|
raise "Invalid scope name: #{@name}" if @name !~ /^[a-zA-Z0-9_-]+$/
|
101
115
|
@name = @name.upcase
|
116
|
+
@scope = @name # Ensure @scope matches @name
|
102
117
|
super(update: update, force: force, queued: queued)
|
118
|
+
|
119
|
+
# If we're updating the scope and disabling command_authority
|
120
|
+
# then we clear out all the existing values so it comes up fresh
|
121
|
+
if update and @command_authority == false
|
122
|
+
CmdAuthorityModel.names(scope: @name).each do |auth_name|
|
123
|
+
model = CmdAuthorityModel.get_model(name: auth_name, scope: @name)
|
124
|
+
model.destroy if model
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
SystemEventsTopic.write(:scope, as_json())
|
103
129
|
end
|
104
130
|
|
105
131
|
def destroy
|
106
132
|
if @name != 'DEFAULT'
|
107
133
|
# Remove all the plugins for this scope
|
108
134
|
plugins = PluginModel.get_all_models(scope: @name)
|
109
|
-
plugins.each do |
|
135
|
+
plugins.each do |_plugin_name, plugin|
|
110
136
|
plugin.destroy
|
111
137
|
end
|
112
138
|
super()
|
@@ -115,7 +141,7 @@ module OpenC3
|
|
115
141
|
end
|
116
142
|
end
|
117
143
|
|
118
|
-
def as_json(*
|
144
|
+
def as_json(*_a)
|
119
145
|
{ 'name' => @name,
|
120
146
|
'updated_at' => @updated_at,
|
121
147
|
'text_log_cycle_time' => @text_log_cycle_time,
|
@@ -123,6 +149,7 @@ module OpenC3
|
|
123
149
|
'text_log_retain_time' => @text_log_retain_time,
|
124
150
|
'tool_log_retain_time' => @tool_log_retain_time,
|
125
151
|
'cleanup_poll_time' => @cleanup_poll_time,
|
152
|
+
'command_authority' => @command_authority,
|
126
153
|
}
|
127
154
|
end
|
128
155
|
|
@@ -276,6 +303,10 @@ module OpenC3
|
|
276
303
|
end
|
277
304
|
|
278
305
|
def undeploy
|
306
|
+
# Delete UNKNOWN target
|
307
|
+
target = TargetModel.get_model(name: "UNKNOWN", scope: @scope)
|
308
|
+
target.destroy
|
309
|
+
|
279
310
|
model = MicroserviceModel.get_model(name: "#{@scope}__SCOPEMULTI__#{@scope}", scope: @scope)
|
280
311
|
model.destroy if model
|
281
312
|
model = MicroserviceModel.get_model(name: "#{@scope}__SCOPECLEANUP__#{@scope}", scope: @scope)
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2024, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -34,15 +34,15 @@ module OpenC3
|
|
34
34
|
class SortedOverlapError < SortedError; end
|
35
35
|
|
36
36
|
class SortedModel < Model
|
37
|
-
SORTED_TYPE = 'sorted'.freeze # To be
|
38
|
-
PRIMARY_KEY = '__SORTED'.freeze # To be
|
37
|
+
SORTED_TYPE = 'sorted'.freeze # To be overridden by base class
|
38
|
+
PRIMARY_KEY = '__SORTED'.freeze # To be overridden by base class
|
39
39
|
|
40
|
-
# MUST be
|
40
|
+
# MUST be overridden by any subclasses
|
41
41
|
def self.pk(scope)
|
42
42
|
return "#{scope}#{PRIMARY_KEY}"
|
43
43
|
end
|
44
44
|
|
45
|
-
# MUST be
|
45
|
+
# MUST be overridden by any subclasses
|
46
46
|
def self.notify(scope:, kind:, start:, stop: nil)
|
47
47
|
# Do nothing by default
|
48
48
|
end
|
@@ -109,7 +109,7 @@ module OpenC3
|
|
109
109
|
modified_targets = Bucket.getClient().list_files(bucket: ENV['OPENC3_CONFIG_BUCKET'], path: "DEFAULT/targets_modified/", only_directories: true)
|
110
110
|
modified_targets.each do |target_name|
|
111
111
|
# A target could have been deleted without removing the modified files
|
112
|
-
# Thus we have to check for the
|
112
|
+
# Thus we have to check for the existence of the target_name key
|
113
113
|
if targets.has_key?(target_name)
|
114
114
|
targets[target_name]['modified'] = true
|
115
115
|
end
|
@@ -250,7 +250,7 @@ module OpenC3
|
|
250
250
|
(items - found_items).each do |item|
|
251
251
|
not_found << "'#{target_name} #{packet_name} #{item}'"
|
252
252
|
end
|
253
|
-
# 'does not exist' not
|
253
|
+
# 'does not exist' not grammatically correct but we use it in every other exception
|
254
254
|
raise "Item(s) #{not_found.join(', ')} does not exist"
|
255
255
|
end
|
256
256
|
found
|
@@ -660,7 +660,10 @@ module OpenC3
|
|
660
660
|
Store.del(item_map_key)
|
661
661
|
@@item_map_cache[@name] = nil
|
662
662
|
|
663
|
-
|
663
|
+
topic = { kind: 'deleted', type: 'target', name: @name }
|
664
|
+
# The UNKNOWN target doesn't have an associated plugin
|
665
|
+
topic[:plugin] = @plugin if @plugin
|
666
|
+
ConfigTopic.write(topic, scope: @scope)
|
664
667
|
rescue Exception => e
|
665
668
|
Logger.error("Error undeploying target model #{@name} in scope #{@scope} due to #{e}")
|
666
669
|
end
|
@@ -1118,7 +1121,7 @@ module OpenC3
|
|
1118
1121
|
end
|
1119
1122
|
end
|
1120
1123
|
# If there are any topics (packets) left over that haven't been
|
1121
|
-
#
|
1124
|
+
# explicitly handled above, spawn another microservice
|
1122
1125
|
if all_topics.length > 0
|
1123
1126
|
instance = nil
|
1124
1127
|
instance = deploy_count unless deploy_count == 0
|
@@ -25,7 +25,7 @@ require 'openc3/utilities/local_mode'
|
|
25
25
|
module OpenC3
|
26
26
|
class ToolConfigModel
|
27
27
|
def self.config_tool_names(scope: $openc3_scope)
|
28
|
-
|
28
|
+
_, keys = Store.scan(0, match: "#{scope}__config__*", type: 'hash', count: 100)
|
29
29
|
# Just return the tool name that is used in the other APIs
|
30
30
|
return keys.map! { |key| key.split('__')[2] }.sort
|
31
31
|
end
|
@@ -96,7 +96,7 @@ module OpenC3
|
|
96
96
|
def self.set_position(name:, position:, scope:)
|
97
97
|
moving = from_json(get(name: name, scope: scope), scope: scope)
|
98
98
|
old_pos = moving.position
|
99
|
-
new_pos =
|
99
|
+
new_pos = position
|
100
100
|
direction = :down
|
101
101
|
if (old_pos == new_pos)
|
102
102
|
return # we're not doing anything
|
@@ -225,7 +225,7 @@ module OpenC3
|
|
225
225
|
@shown = ConfigParser.handle_true_false(parameters[0])
|
226
226
|
when 'POSITION'
|
227
227
|
parser.verify_num_parameters(1, 1, "POSITION <value>")
|
228
|
-
@position = parameters[0].
|
228
|
+
@position = parameters[0].to_f
|
229
229
|
when 'DISABLE_ERB'
|
230
230
|
# 0 to unlimited parameters
|
231
231
|
@disable_erb ||= []
|
@@ -274,8 +274,8 @@ module OpenC3
|
|
274
274
|
ConfigTopic.write({ kind: 'deleted', type: 'tool', name: @folder_name, plugin: @plugin }, scope: @scope)
|
275
275
|
end
|
276
276
|
end
|
277
|
-
rescue Exception =>
|
278
|
-
Logger.error("Error undeploying tool model #{@name} in scope #{@scope} due to #{
|
277
|
+
rescue Exception => e
|
278
|
+
Logger.error("Error undeploying tool model #{@name} in scope #{@scope} due to #{e}")
|
279
279
|
end
|
280
280
|
|
281
281
|
##################################################
|
@@ -73,9 +73,11 @@ module OpenC3
|
|
73
73
|
def self.handle_config(parser, keyword, parameters, plugin: nil, needs_dependencies: false, scope:)
|
74
74
|
case keyword
|
75
75
|
when 'WIDGET'
|
76
|
-
parser.verify_num_parameters(1,
|
76
|
+
parser.verify_num_parameters(1, 3, "WIDGET <Name> <Label> <Select Items (true/false)>")
|
77
77
|
# Label is optional and if it doesn't exist nil is fine
|
78
|
-
|
78
|
+
# Select Items is optional and if it doesn't exist nil is fine
|
79
|
+
items = ConfigParser.handle_true_false_nil(parameters[2])
|
80
|
+
return self.new(name: parameters[0], plugin: plugin, label: parameters[1], items: items, needs_dependencies: needs_dependencies, scope: scope)
|
79
81
|
else
|
80
82
|
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Widget: #{keyword} #{parameters.join(" ")}")
|
81
83
|
end
|
@@ -87,6 +89,7 @@ module OpenC3
|
|
87
89
|
updated_at: nil,
|
88
90
|
plugin: nil,
|
89
91
|
label: nil,
|
92
|
+
items: false,
|
90
93
|
needs_dependencies: false,
|
91
94
|
disable_erb: nil,
|
92
95
|
scope:
|
@@ -96,6 +99,8 @@ module OpenC3
|
|
96
99
|
@filename = @full_name + '.umd.min.js'
|
97
100
|
@bucket_key = 'widgets/' + @full_name + '/' + @filename
|
98
101
|
@label = label
|
102
|
+
# Ensure items is a boolean because it could be nil
|
103
|
+
@items = items ? true : false
|
99
104
|
@needs_dependencies = needs_dependencies
|
100
105
|
@disable_erb = disable_erb
|
101
106
|
end
|
@@ -106,8 +111,9 @@ module OpenC3
|
|
106
111
|
'updated_at' => @updated_at,
|
107
112
|
'plugin' => @plugin,
|
108
113
|
'label' => @label,
|
114
|
+
'items' => @items,
|
109
115
|
'needs_dependencies' => @needs_dependencies,
|
110
|
-
'disable_erb' => @disable_erb
|
116
|
+
'disable_erb' => @disable_erb,
|
111
117
|
}
|
112
118
|
end
|
113
119
|
|
@@ -155,8 +161,8 @@ module OpenC3
|
|
155
161
|
bucket = Bucket.getClient()
|
156
162
|
bucket.delete_object(bucket: ENV['OPENC3_TOOLS_BUCKET'], key: @bucket_key)
|
157
163
|
bucket.delete_object(bucket: ENV['OPENC3_TOOLS_BUCKET'], key: @bucket_key + '.map')
|
158
|
-
rescue Exception =>
|
159
|
-
Logger.error("Error undeploying widget model #{@name} in scope #{@scope} due to #{
|
164
|
+
rescue Exception => e
|
165
|
+
Logger.error("Error undeploying widget model #{@name} in scope #{@scope} due to #{e}")
|
160
166
|
end
|
161
167
|
end
|
162
168
|
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# GNU Affero General Public License for more details.
|
15
15
|
|
16
16
|
# Modified by OpenC3, Inc.
|
17
|
-
# All changes Copyright
|
17
|
+
# All changes Copyright 2024, OpenC3, Inc.
|
18
18
|
# All Rights Reserved
|
19
19
|
#
|
20
20
|
# This file may also be used under the terms of a commercial license
|
@@ -186,7 +186,7 @@ module OpenC3
|
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
189
|
-
@removed_microservices.each do |microservice_name,
|
189
|
+
@removed_microservices.each do |microservice_name, _microservice_config|
|
190
190
|
process = @processes[microservice_name]
|
191
191
|
@processes.delete(microservice_name)
|
192
192
|
@removed_processes[microservice_name] = process
|
@@ -105,7 +105,7 @@ module OpenC3
|
|
105
105
|
def cmd_line
|
106
106
|
# In ProcessManager processes, the process_definition is the actual thing run
|
107
107
|
# e.g. OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "load", ...])
|
108
|
-
# However, if the MicroserviceOperator is spawning the
|
108
|
+
# However, if the MicroserviceOperator is spawning the processes it sets
|
109
109
|
# process_definition = ["ruby", "plugin_microservice.rb"]
|
110
110
|
# which then calls exec(*@config["cmd"]) to actually run
|
111
111
|
# So check if the @config['cmd'] is defined to give the user more info in the log
|
@@ -127,7 +127,7 @@ module OpenC3
|
|
127
127
|
# @process.io.inherit!
|
128
128
|
@process.cwd = @work_dir
|
129
129
|
# Spawned process should not be controlled by same Bundler constraints as spawning process
|
130
|
-
ENV.each do |key,
|
130
|
+
ENV.each do |key, _value|
|
131
131
|
if key =~ /^BUNDLER/
|
132
132
|
@process.environment[key] = nil
|
133
133
|
end
|
@@ -195,12 +195,14 @@ module OpenC3
|
|
195
195
|
if @process
|
196
196
|
stdout = @process.io.stdout.extract
|
197
197
|
if stdout.length > 0
|
198
|
-
|
198
|
+
message = "STDOUT #{stdout.length} bytes from #{cmd_line()}:"
|
199
|
+
STDOUT.puts Logger.build_log_data(Logger::INFO_LEVEL, message, user: nil, type: OpenC3::Logger::LOG, url: nil).as_json(:allow_nan => true).to_json(:allow_nan => true)
|
199
200
|
STDOUT.puts stdout
|
200
201
|
end
|
201
202
|
stderr = @process.io.stderr.extract
|
202
203
|
if stderr.length > 0
|
203
|
-
|
204
|
+
message = "STDERR #{stderr.length} bytes from #{cmd_line()}:"
|
205
|
+
STDERR.puts Logger.build_log_data(Logger::ERROR_LEVEL, message, user: nil, type: OpenC3::Logger::LOG, url: nil).as_json(:allow_nan => true).to_json(:allow_nan => true)
|
204
206
|
STDERR.puts stderr
|
205
207
|
end
|
206
208
|
end
|
@@ -265,7 +267,7 @@ module OpenC3
|
|
265
267
|
if @new_processes.length > 0
|
266
268
|
# Start all the processes
|
267
269
|
Logger.info("#{self.class} starting each new process...")
|
268
|
-
@new_processes.each { |
|
270
|
+
@new_processes.each { |_name, p| p.start }
|
269
271
|
@new_processes = {}
|
270
272
|
end
|
271
273
|
end
|
@@ -278,7 +280,7 @@ module OpenC3
|
|
278
280
|
shutdown_processes(@changed_processes)
|
279
281
|
break if @shutdown
|
280
282
|
|
281
|
-
@changed_processes.each { |
|
283
|
+
@changed_processes.each { |_name, p| p.start }
|
282
284
|
@changed_processes = {}
|
283
285
|
end
|
284
286
|
end
|
@@ -296,7 +298,7 @@ module OpenC3
|
|
296
298
|
|
297
299
|
def respawn_dead
|
298
300
|
@mutex.synchronize do
|
299
|
-
@processes.each do |
|
301
|
+
@processes.each do |_name, p|
|
300
302
|
break if @shutdown
|
301
303
|
p.output_increment
|
302
304
|
unless p.alive?
|
@@ -314,7 +316,7 @@ module OpenC3
|
|
314
316
|
processes = processes.dup
|
315
317
|
|
316
318
|
Logger.info("Commanding soft stops...")
|
317
|
-
processes.each { |
|
319
|
+
processes.each { |_name, p| p.soft_stop }
|
318
320
|
start_time = Time.now
|
319
321
|
# Allow sufficient time for processes to shutdown cleanly
|
320
322
|
while (Time.now - start_time) < PROCESS_SHUTDOWN_SECONDS
|
@@ -322,21 +324,21 @@ module OpenC3
|
|
322
324
|
processes.each do |name, p|
|
323
325
|
unless p.alive?
|
324
326
|
processes_to_remove << name
|
325
|
-
Logger.
|
327
|
+
Logger.debug("Soft stop process successful: #{p.cmd_line}", scope: p.scope)
|
326
328
|
end
|
327
329
|
end
|
328
330
|
processes_to_remove.each do |name|
|
329
331
|
processes.delete(name)
|
330
332
|
end
|
331
333
|
if processes.length <= 0
|
332
|
-
Logger.
|
334
|
+
Logger.debug("Soft stop all successful")
|
333
335
|
break
|
334
336
|
end
|
335
337
|
sleep(0.1)
|
336
338
|
end
|
337
339
|
if processes.length > 0
|
338
|
-
Logger.
|
339
|
-
processes.each { |
|
340
|
+
Logger.debug("Commanding hard stops...")
|
341
|
+
processes.each { |_name, p| p.hard_stop }
|
340
342
|
end
|
341
343
|
end
|
342
344
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: ascii-8bit
|
2
|
+
|
3
|
+
# Copyright 2024 OpenC3, Inc.
|
4
|
+
# All Rights Reserved.
|
5
|
+
#
|
6
|
+
# This program is free software; you can modify and/or redistribute it
|
7
|
+
# under the terms of the GNU Affero General Public License
|
8
|
+
# as published by the Free Software Foundation; version 3 with
|
9
|
+
# attribution addendums as found in the LICENSE.txt
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
|
16
|
+
# This file may also be used under the terms of a commercial license
|
17
|
+
# if purchased from OpenC3, Inc.
|
18
|
+
|
19
|
+
# This file implements a class to handle command validation
|
20
|
+
|
21
|
+
require 'openc3/api/api'
|
22
|
+
|
23
|
+
module OpenC3
|
24
|
+
# This class defines methods which are called when a command is sent.
|
25
|
+
# This class must be subclassed and the pre_check or
|
26
|
+
# post_check methods implemented. Do NOT use this class directly.
|
27
|
+
class CommandValidator
|
28
|
+
attr_reader :args
|
29
|
+
include Api
|
30
|
+
|
31
|
+
def initialize(command = nil)
|
32
|
+
@command = command
|
33
|
+
@args = []
|
34
|
+
end
|
35
|
+
|
36
|
+
def pre_check(command)
|
37
|
+
# Return true to indicate Success, false to indicate Failure,
|
38
|
+
# and nil to indicate Unknown. The second value is the optional message.
|
39
|
+
return [true, nil]
|
40
|
+
end
|
41
|
+
|
42
|
+
def post_check(command)
|
43
|
+
# Return true to indicate Success, false to indicate Failure,
|
44
|
+
# and nil to indicate Unknown. The second value is the optional message.
|
45
|
+
return [true, nil]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -30,7 +30,7 @@ module OpenC3
|
|
30
30
|
#
|
31
31
|
# This should not be confused with the Api module which implements the JSON
|
32
32
|
# API that is used by tools when accessing the Server. The Api module always
|
33
|
-
# provides Ruby
|
33
|
+
# provides Ruby primitives where the PacketConfig class can return actual
|
34
34
|
# Packet or PacketItem objects. While there are some overlapping methods between
|
35
35
|
# the two, these are separate interfaces into the system.
|
36
36
|
class Commands
|
@@ -115,7 +115,7 @@ module OpenC3
|
|
115
115
|
target = System.targets[target_name]
|
116
116
|
if target and target.cmd_unique_id_mode
|
117
117
|
# Iterate through the packets and see if any represent the buffer
|
118
|
-
target_packets.each do |
|
118
|
+
target_packets.each do |_packet_name, packet|
|
119
119
|
if packet.identify?(packet_data)
|
120
120
|
identified_packet = packet
|
121
121
|
break
|
@@ -147,7 +147,7 @@ module OpenC3
|
|
147
147
|
end
|
148
148
|
|
149
149
|
# Returns a copy of the specified command packet with the parameters
|
150
|
-
#
|
150
|
+
# initialized to the given params values.
|
151
151
|
#
|
152
152
|
# @param target_name (see #packet)
|
153
153
|
# @param packet_name (see #packet)
|
@@ -195,7 +195,7 @@ module OpenC3
|
|
195
195
|
items = packet.read_all(:FORMATTED)
|
196
196
|
raw = false
|
197
197
|
end
|
198
|
-
items.delete_if { |item_name,
|
198
|
+
items.delete_if { |item_name, _item_value| ignored_parameters.include?(item_name) }
|
199
199
|
return build_cmd_output_string(packet.target_name, packet.packet_name, items, raw)
|
200
200
|
end
|
201
201
|
|
@@ -207,7 +207,7 @@ module OpenC3
|
|
207
207
|
end
|
208
208
|
target_name = 'UNKNOWN' unless target_name
|
209
209
|
cmd_name = 'UNKNOWN' unless cmd_name
|
210
|
-
output_string << target_name + ' ' + cmd_name
|
210
|
+
output_string << (target_name + ' ' + cmd_name)
|
211
211
|
if cmd_params.nil? or cmd_params.empty?
|
212
212
|
output_string << '")'
|
213
213
|
else
|
@@ -247,7 +247,7 @@ module OpenC3
|
|
247
247
|
params << "#{key} #{value}"
|
248
248
|
end
|
249
249
|
params = params.join(", ")
|
250
|
-
output_string << ' with ' + params + '")'
|
250
|
+
output_string << (' with ' + params + '")')
|
251
251
|
end
|
252
252
|
return output_string
|
253
253
|
end
|
@@ -291,14 +291,6 @@ module OpenC3
|
|
291
291
|
cmd_pkt_hazardous?(build_cmd(target_name, packet_name, params, false, false, false))
|
292
292
|
end
|
293
293
|
|
294
|
-
def clear_counters
|
295
|
-
@config.commands.each do |target_name, target_packets|
|
296
|
-
target_packets.each do |packet_name, packet|
|
297
|
-
packet.received_count = 0
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
|
302
294
|
def all
|
303
295
|
@config.commands
|
304
296
|
end
|