openc3 5.0.6
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 +7 -0
- data/Gemfile +18 -0
- data/Guardfile +35 -0
- data/LICENSE.txt +727 -0
- data/README.md +37 -0
- data/Rakefile +131 -0
- data/bin/cstol_converter +1178 -0
- data/bin/openc3cli +531 -0
- data/bin/rubysloc +139 -0
- data/data/config/_array_params.yaml +23 -0
- data/data/config/_id_items.yaml +24 -0
- data/data/config/_id_params.yaml +58 -0
- data/data/config/_interfaces.yaml +214 -0
- data/data/config/_interfaces.yaml.err +1017 -0
- data/data/config/_items.yaml +20 -0
- data/data/config/_params.yaml +60 -0
- data/data/config/cmd_tlm_server.yaml +136 -0
- data/data/config/command.yaml +44 -0
- data/data/config/command_modifiers.yaml +160 -0
- data/data/config/command_telemetry.yaml +3 -0
- data/data/config/interface_modifiers.yaml +104 -0
- data/data/config/item_modifiers.yaml +221 -0
- data/data/config/microservice.yaml +78 -0
- data/data/config/param_item_modifiers.yaml +52 -0
- data/data/config/parameter_modifiers.yaml +200 -0
- data/data/config/plugins.yaml +80 -0
- data/data/config/protocols.yaml +290 -0
- data/data/config/screen.yaml +147 -0
- data/data/config/table_manager.yaml +89 -0
- data/data/config/table_parameter_modifiers.yaml +9 -0
- data/data/config/target.yaml +142 -0
- data/data/config/target_config.yaml +94 -0
- data/data/config/telemetry.yaml +87 -0
- data/data/config/telemetry_modifiers.yaml +159 -0
- data/data/config/tool.yaml +63 -0
- data/data/config/unknown.yaml +3 -0
- data/data/config/widgets.yaml +1505 -0
- data/ext/mkrf_conf.rb +49 -0
- data/ext/openc3/ext/array/array.c +122 -0
- data/ext/openc3/ext/array/extconf.rb +13 -0
- data/ext/openc3/ext/buffered_file/buffered_file.c +198 -0
- data/ext/openc3/ext/buffered_file/extconf.rb +13 -0
- data/ext/openc3/ext/config_parser/config_parser.c +280 -0
- data/ext/openc3/ext/config_parser/extconf.rb +13 -0
- data/ext/openc3/ext/crc/crc.c +351 -0
- data/ext/openc3/ext/crc/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/extconf.rb +13 -0
- data/ext/openc3/ext/openc3_io/openc3_io.c +158 -0
- data/ext/openc3/ext/packet/extconf.rb +13 -0
- data/ext/openc3/ext/packet/packet.c +318 -0
- data/ext/openc3/ext/platform/extconf.rb +13 -0
- data/ext/openc3/ext/platform/platform.c +134 -0
- data/ext/openc3/ext/polynomial_conversion/extconf.rb +13 -0
- data/ext/openc3/ext/polynomial_conversion/polynomial_conversion.c +79 -0
- data/ext/openc3/ext/string/extconf.rb +13 -0
- data/ext/openc3/ext/string/string.c +63 -0
- data/ext/openc3/ext/structure/structure.c +1719 -0
- data/ext/openc3/ext/tabbed_plots_config/extconf.rb +13 -0
- data/ext/openc3/ext/tabbed_plots_config/tabbed_plots_config.c +62 -0
- data/ext/openc3/ext/telemetry/extconf.rb +13 -0
- data/ext/openc3/ext/telemetry/telemetry.c +336 -0
- data/lib/cosmos.rb +20 -0
- data/lib/cosmosc2.rb +20 -0
- data/lib/openc3/api/api.rb +39 -0
- data/lib/openc3/api/authorized_api.rb +30 -0
- data/lib/openc3/api/cmd_api.rb +451 -0
- data/lib/openc3/api/config_api.rb +58 -0
- data/lib/openc3/api/interface_api.rb +117 -0
- data/lib/openc3/api/limits_api.rb +375 -0
- data/lib/openc3/api/router_api.rb +117 -0
- data/lib/openc3/api/settings_api.rb +70 -0
- data/lib/openc3/api/target_api.rb +78 -0
- data/lib/openc3/api/tlm_api.rb +455 -0
- data/lib/openc3/bridge/bridge.rb +54 -0
- data/lib/openc3/bridge/bridge_config.rb +167 -0
- data/lib/openc3/bridge/bridge_interface_thread.rb +42 -0
- data/lib/openc3/bridge/bridge_router_thread.rb +42 -0
- data/lib/openc3/ccsds/ccsds_packet.rb +68 -0
- data/lib/openc3/ccsds/ccsds_parser.rb +148 -0
- data/lib/openc3/config/config_parser.rb +549 -0
- data/lib/openc3/config/meta_config_parser.rb +74 -0
- data/lib/openc3/conversions/conversion.rb +70 -0
- data/lib/openc3/conversions/generic_conversion.rb +83 -0
- data/lib/openc3/conversions/packet_time_formatted_conversion.rb +43 -0
- data/lib/openc3/conversions/packet_time_seconds_conversion.rb +43 -0
- data/lib/openc3/conversions/polynomial_conversion.rb +87 -0
- data/lib/openc3/conversions/processor_conversion.rb +70 -0
- data/lib/openc3/conversions/received_count_conversion.rb +38 -0
- data/lib/openc3/conversions/received_time_formatted_conversion.rb +42 -0
- data/lib/openc3/conversions/received_time_seconds_conversion.rb +42 -0
- data/lib/openc3/conversions/segmented_polynomial_conversion.rb +171 -0
- data/lib/openc3/conversions/unix_time_conversion.rb +68 -0
- data/lib/openc3/conversions/unix_time_formatted_conversion.rb +49 -0
- data/lib/openc3/conversions/unix_time_seconds_conversion.rb +49 -0
- data/lib/openc3/conversions.rb +34 -0
- data/lib/openc3/core_ext/array.rb +416 -0
- data/lib/openc3/core_ext/binding.rb +29 -0
- data/lib/openc3/core_ext/class.rb +72 -0
- data/lib/openc3/core_ext/exception.rb +61 -0
- data/lib/openc3/core_ext/file.rb +83 -0
- data/lib/openc3/core_ext/hash.rb +37 -0
- data/lib/openc3/core_ext/io.rb +134 -0
- data/lib/openc3/core_ext/kernel.rb +42 -0
- data/lib/openc3/core_ext/math.rb +128 -0
- data/lib/openc3/core_ext/matrix.rb +156 -0
- data/lib/openc3/core_ext/objectspace.rb +36 -0
- data/lib/openc3/core_ext/openc3_io.rb +57 -0
- data/lib/openc3/core_ext/range.rb +27 -0
- data/lib/openc3/core_ext/socket.rb +38 -0
- data/lib/openc3/core_ext/string.rb +389 -0
- data/lib/openc3/core_ext/stringio.rb +33 -0
- data/lib/openc3/core_ext/time.rb +508 -0
- data/lib/openc3/core_ext.rb +36 -0
- data/lib/openc3/interfaces/interface.rb +498 -0
- data/lib/openc3/interfaces/linc_interface.rb +475 -0
- data/lib/openc3/interfaces/protocols/burst_protocol.rb +192 -0
- data/lib/openc3/interfaces/protocols/crc_protocol.rb +193 -0
- data/lib/openc3/interfaces/protocols/fixed_protocol.rb +155 -0
- data/lib/openc3/interfaces/protocols/ignore_packet_protocol.rb +56 -0
- data/lib/openc3/interfaces/protocols/length_protocol.rb +165 -0
- data/lib/openc3/interfaces/protocols/override_protocol.rb +60 -0
- data/lib/openc3/interfaces/protocols/preidentified_protocol.rb +206 -0
- data/lib/openc3/interfaces/protocols/protocol.rb +82 -0
- data/lib/openc3/interfaces/protocols/template_protocol.rb +261 -0
- data/lib/openc3/interfaces/protocols/terminated_protocol.rb +93 -0
- data/lib/openc3/interfaces/serial_interface.rb +94 -0
- data/lib/openc3/interfaces/simulated_target_interface.rb +168 -0
- data/lib/openc3/interfaces/stream_interface.rb +81 -0
- data/lib/openc3/interfaces/tcpip_client_interface.rb +69 -0
- data/lib/openc3/interfaces/tcpip_server_interface.rb +629 -0
- data/lib/openc3/interfaces/udp_interface.rb +169 -0
- data/lib/openc3/interfaces.rb +44 -0
- data/lib/openc3/io/buffered_file.rb +109 -0
- data/lib/openc3/io/io_multiplexer.rb +80 -0
- data/lib/openc3/io/json_api_object.rb +208 -0
- data/lib/openc3/io/json_drb.rb +335 -0
- data/lib/openc3/io/json_drb_object.rb +114 -0
- data/lib/openc3/io/json_drb_rack.rb +84 -0
- data/lib/openc3/io/json_rpc.rb +420 -0
- data/lib/openc3/io/openc3_snmp.rb +58 -0
- data/lib/openc3/io/posix_serial_driver.rb +156 -0
- data/lib/openc3/io/raw_logger.rb +167 -0
- data/lib/openc3/io/raw_logger_pair.rb +77 -0
- data/lib/openc3/io/serial_driver.rb +105 -0
- data/lib/openc3/io/stderr.rb +43 -0
- data/lib/openc3/io/stdout.rb +43 -0
- data/lib/openc3/io/udp_sockets.rb +194 -0
- data/lib/openc3/io/win32_serial_driver.rb +196 -0
- data/lib/openc3/logs/log_writer.rb +302 -0
- data/lib/openc3/logs/packet_log_constants.rb +62 -0
- data/lib/openc3/logs/packet_log_reader.rb +345 -0
- data/lib/openc3/logs/packet_log_writer.rb +299 -0
- data/lib/openc3/logs/text_log_writer.rb +68 -0
- data/lib/openc3/logs.rb +25 -0
- data/lib/openc3/microservices/cleanup_microservice.rb +68 -0
- data/lib/openc3/microservices/decom_microservice.rb +136 -0
- data/lib/openc3/microservices/interface_microservice.rb +532 -0
- data/lib/openc3/microservices/log_microservice.rb +108 -0
- data/lib/openc3/microservices/microservice.rb +204 -0
- data/lib/openc3/microservices/plugin_microservice.rb +43 -0
- data/lib/openc3/microservices/reaction_microservice.rb +541 -0
- data/lib/openc3/microservices/reducer_microservice.rb +313 -0
- data/lib/openc3/microservices/router_microservice.rb +44 -0
- data/lib/openc3/microservices/text_log_microservice.rb +84 -0
- data/lib/openc3/microservices/timeline_microservice.rb +363 -0
- data/lib/openc3/microservices/trigger_group_microservice.rb +638 -0
- data/lib/openc3/models/activity_model.rb +319 -0
- data/lib/openc3/models/auth_model.rb +65 -0
- data/lib/openc3/models/cvt_model.rb +185 -0
- data/lib/openc3/models/environment_model.rb +58 -0
- data/lib/openc3/models/gem_model.rb +137 -0
- data/lib/openc3/models/info_model.rb +31 -0
- data/lib/openc3/models/interface_model.rb +281 -0
- data/lib/openc3/models/interface_status_model.rb +117 -0
- data/lib/openc3/models/metadata_model.rb +139 -0
- data/lib/openc3/models/metric_model.rb +59 -0
- data/lib/openc3/models/microservice_model.rb +206 -0
- data/lib/openc3/models/microservice_status_model.rb +74 -0
- data/lib/openc3/models/model.rb +204 -0
- data/lib/openc3/models/note_model.rb +122 -0
- data/lib/openc3/models/notification_model.rb +40 -0
- data/lib/openc3/models/ping_model.rb +35 -0
- data/lib/openc3/models/plugin_model.rb +292 -0
- data/lib/openc3/models/process_status_model.rb +76 -0
- data/lib/openc3/models/reaction_model.rb +322 -0
- data/lib/openc3/models/reducer_model.rb +65 -0
- data/lib/openc3/models/router_model.rb +35 -0
- data/lib/openc3/models/router_status_model.rb +27 -0
- data/lib/openc3/models/scope_model.rb +153 -0
- data/lib/openc3/models/settings_model.rb +55 -0
- data/lib/openc3/models/sorted_model.rb +167 -0
- data/lib/openc3/models/target_model.rb +759 -0
- data/lib/openc3/models/timeline_model.rb +154 -0
- data/lib/openc3/models/tool_config_model.rb +38 -0
- data/lib/openc3/models/tool_model.rb +262 -0
- data/lib/openc3/models/trigger_group_model.rb +186 -0
- data/lib/openc3/models/trigger_model.rb +330 -0
- data/lib/openc3/models/widget_model.rb +138 -0
- data/lib/openc3/operators/microservice_operator.rb +128 -0
- data/lib/openc3/operators/operator.rb +277 -0
- data/lib/openc3/packets/binary_accessor.rb +1207 -0
- data/lib/openc3/packets/commands.rb +373 -0
- data/lib/openc3/packets/json_packet.rb +134 -0
- data/lib/openc3/packets/limits.rb +271 -0
- data/lib/openc3/packets/limits_response.rb +53 -0
- data/lib/openc3/packets/packet.rb +1168 -0
- data/lib/openc3/packets/packet_config.rb +625 -0
- data/lib/openc3/packets/packet_item.rb +586 -0
- data/lib/openc3/packets/packet_item_limits.rb +162 -0
- data/lib/openc3/packets/parsers/format_string_parser.rb +65 -0
- data/lib/openc3/packets/parsers/limits_parser.rb +159 -0
- data/lib/openc3/packets/parsers/limits_response_parser.rb +61 -0
- data/lib/openc3/packets/parsers/packet_item_parser.rb +272 -0
- data/lib/openc3/packets/parsers/packet_parser.rb +134 -0
- data/lib/openc3/packets/parsers/processor_parser.rb +73 -0
- data/lib/openc3/packets/parsers/state_parser.rb +127 -0
- data/lib/openc3/packets/parsers/xtce_converter.rb +442 -0
- data/lib/openc3/packets/parsers/xtce_parser.rb +722 -0
- data/lib/openc3/packets/structure.rb +553 -0
- data/lib/openc3/packets/structure_item.rb +365 -0
- data/lib/openc3/packets/telemetry.rb +487 -0
- data/lib/openc3/processors/processor.rb +86 -0
- data/lib/openc3/processors/statistics_processor.rb +82 -0
- data/lib/openc3/processors/watermark_processor.rb +58 -0
- data/lib/openc3/processors.rb +24 -0
- data/lib/openc3/script/api_shared.rb +828 -0
- data/lib/openc3/script/calendar.rb +89 -0
- data/lib/openc3/script/commands.rb +227 -0
- data/lib/openc3/script/exceptions.rb +29 -0
- data/lib/openc3/script/extract.rb +161 -0
- data/lib/openc3/script/limits.rb +60 -0
- data/lib/openc3/script/script.rb +299 -0
- data/lib/openc3/script/script_runner.rb +238 -0
- data/lib/openc3/script/storage.rb +146 -0
- data/lib/openc3/script/suite.rb +542 -0
- data/lib/openc3/script/suite_results.rb +196 -0
- data/lib/openc3/script/suite_runner.rb +217 -0
- data/lib/openc3/script.rb +21 -0
- data/lib/openc3/streams/serial_stream.rb +167 -0
- data/lib/openc3/streams/stream.rb +63 -0
- data/lib/openc3/streams/tcpip_client_stream.rb +116 -0
- data/lib/openc3/streams/tcpip_socket_stream.rb +195 -0
- data/lib/openc3/system/system.rb +127 -0
- data/lib/openc3/system/system_config.rb +411 -0
- data/lib/openc3/system/target.rb +269 -0
- data/lib/openc3/system.rb +24 -0
- data/lib/openc3/tools/cmd_tlm_server/api.rb +20 -0
- data/lib/openc3/tools/cmd_tlm_server/cmd_tlm_server_config.rb +320 -0
- data/lib/openc3/tools/cmd_tlm_server/interface_thread.rb +294 -0
- data/lib/openc3/tools/table_manager/table.rb +77 -0
- data/lib/openc3/tools/table_manager/table_config.rb +273 -0
- data/lib/openc3/tools/table_manager/table_item.rb +90 -0
- data/lib/openc3/tools/table_manager/table_item_parser.rb +66 -0
- data/lib/openc3/tools/table_manager/table_manager_core.rb +333 -0
- data/lib/openc3/tools/table_manager/table_parser.rb +93 -0
- data/lib/openc3/tools/test_runner/test.rb +67 -0
- data/lib/openc3/top_level.rb +595 -0
- data/lib/openc3/topics/autonomic_topic.rb +52 -0
- data/lib/openc3/topics/calendar_topic.rb +44 -0
- data/lib/openc3/topics/command_decom_topic.rb +76 -0
- data/lib/openc3/topics/command_topic.rb +83 -0
- data/lib/openc3/topics/config_topic.rb +68 -0
- data/lib/openc3/topics/interface_topic.rb +73 -0
- data/lib/openc3/topics/limits_event_topic.rb +109 -0
- data/lib/openc3/topics/notifications_topic.rb +28 -0
- data/lib/openc3/topics/router_topic.rb +85 -0
- data/lib/openc3/topics/telemetry_decom_topic.rb +54 -0
- data/lib/openc3/topics/telemetry_topic.rb +36 -0
- data/lib/openc3/topics/timeline_topic.rb +45 -0
- data/lib/openc3/topics/topic.rb +53 -0
- data/lib/openc3/utilities/authentication.rb +141 -0
- data/lib/openc3/utilities/authorization.rb +51 -0
- data/lib/openc3/utilities/crc.rb +278 -0
- data/lib/openc3/utilities/csv.rb +153 -0
- data/lib/openc3/utilities/logger.rb +187 -0
- data/lib/openc3/utilities/message_log.rb +91 -0
- data/lib/openc3/utilities/metric.rb +141 -0
- data/lib/openc3/utilities/process_manager.rb +139 -0
- data/lib/openc3/utilities/quaternion.rb +257 -0
- data/lib/openc3/utilities/ruby_lex_utils.rb +568 -0
- data/lib/openc3/utilities/s3.rb +202 -0
- data/lib/openc3/utilities/s3_autoload.rb +9 -0
- data/lib/openc3/utilities/s3_file_cache.rb +274 -0
- data/lib/openc3/utilities/simulated_target.rb +117 -0
- data/lib/openc3/utilities/sleeper.rb +51 -0
- data/lib/openc3/utilities/store.rb +23 -0
- data/lib/openc3/utilities/store_autoload.rb +237 -0
- data/lib/openc3/utilities/zip.rb +21 -0
- data/lib/openc3/utilities.rb +35 -0
- data/lib/openc3/version.rb +14 -0
- data/lib/openc3/win32/excel.rb +132 -0
- data/lib/openc3/win32/win32.rb +402 -0
- data/lib/openc3/win32/win32_main.rb +333 -0
- data/lib/openc3.rb +49 -0
- data/tasks/gemfile_stats.rake +113 -0
- data/tasks/spec.rake +30 -0
- data/templates/plugin-template/README.md +15 -0
- data/templates/plugin-template/Rakefile +12 -0
- data/templates/plugin-template/plugin.gemspec +23 -0
- data/templates/plugin-template/plugin.txt +9 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/cmd.txt +8 -0
- data/templates/plugin-template/targets/TARGET/cmd_tlm/tlm.txt +8 -0
- data/templates/plugin-template/targets/TARGET/lib/target.rb +10 -0
- data/templates/plugin-template/targets/TARGET/procedures/procedure.rb +3 -0
- data/templates/plugin-template/targets/TARGET/screens/status.txt +9 -0
- data/templates/plugin-template/targets/TARGET/target.txt +5 -0
- metadata +849 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# encoding: ascii-8bit
|
|
2
|
+
|
|
3
|
+
# Copyright 2022 Ball Aerospace & Technologies Corp.
|
|
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
|
+
# Modified by OpenC3, Inc.
|
|
17
|
+
# All changes Copyright 2022, OpenC3, Inc.
|
|
18
|
+
# All Rights Reserved
|
|
19
|
+
|
|
20
|
+
require 'openc3/utilities/authentication'
|
|
21
|
+
require 'openc3/microservices/microservice'
|
|
22
|
+
require 'openc3/models/activity_model'
|
|
23
|
+
require 'openc3/models/notification_model'
|
|
24
|
+
require 'openc3/models/timeline_model'
|
|
25
|
+
require 'openc3/topics/timeline_topic'
|
|
26
|
+
|
|
27
|
+
require 'openc3/script'
|
|
28
|
+
|
|
29
|
+
module OpenC3
|
|
30
|
+
# The Timeline worker is a very simple thread pool worker. Once
|
|
31
|
+
# the timeline manager has pushed a job to the schedule one of
|
|
32
|
+
# these workers will run the CMD (command) or SCRIPT (script)
|
|
33
|
+
# or anything that could be expanded in the future.
|
|
34
|
+
class TimelineWorker
|
|
35
|
+
def initialize(name:, scope:, queue:)
|
|
36
|
+
@timeline_name = name
|
|
37
|
+
@scope = scope
|
|
38
|
+
@queue = queue
|
|
39
|
+
@authentication = generate_auth()
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# generate the auth object
|
|
43
|
+
def generate_auth
|
|
44
|
+
if ENV['OPENC3_API_USER'].nil? || ENV['OPENC3_API_CLIENT'].nil?
|
|
45
|
+
return OpenC3Authentication.new()
|
|
46
|
+
else
|
|
47
|
+
return OpenC3KeycloakAuthentication.new(ENV['OPENC3_KEYCLOAK_URL'])
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def run
|
|
52
|
+
Logger.info "#{@timeline_name} timeline worker running"
|
|
53
|
+
loop do
|
|
54
|
+
activity = @queue.pop
|
|
55
|
+
break if activity.nil?
|
|
56
|
+
|
|
57
|
+
run_activity(activity)
|
|
58
|
+
end
|
|
59
|
+
Logger.info "#{@timeline_name} timeine worker exiting"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def run_activity(activity)
|
|
63
|
+
case activity.kind.upcase
|
|
64
|
+
when 'COMMAND'
|
|
65
|
+
run_command(activity)
|
|
66
|
+
when 'SCRIPT'
|
|
67
|
+
run_script(activity)
|
|
68
|
+
when 'EXPIRE'
|
|
69
|
+
clear_expired(activity)
|
|
70
|
+
else
|
|
71
|
+
Logger.error "Unknown kind passed to microservice #{@timeline_name}: #{activity.as_json(:allow_nan => true)}"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def run_command(activity)
|
|
76
|
+
Logger.info "#{@timeline_name} run_command > #{activity.as_json(:allow_nan => true)}"
|
|
77
|
+
begin
|
|
78
|
+
cmd_no_hazardous_check(activity.data['command'], scope: @scope)
|
|
79
|
+
activity.commit(status: 'completed', fulfillment: true)
|
|
80
|
+
rescue StandardError => e
|
|
81
|
+
activity.commit(status: 'failed', message: e.message)
|
|
82
|
+
Logger.error "#{@timeline_name} run_cmd failed > #{activity.as_json(:allow_nan => true)}, #{e.message}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def run_script(activity)
|
|
87
|
+
Logger.info "#{@timeline_name} run_script > #{activity.as_json(:allow_nan => true)}"
|
|
88
|
+
begin
|
|
89
|
+
request = Net::HTTP::Post.new(
|
|
90
|
+
"/script-api/scripts/#{activity.data['script']}/run?scope=#{@scope}",
|
|
91
|
+
'Content-Type' => 'application/json',
|
|
92
|
+
'Authorization' => @authentication.token()
|
|
93
|
+
)
|
|
94
|
+
request.body = JSON.generate({
|
|
95
|
+
'scope' => @scope,
|
|
96
|
+
'environment' => activity.data['environment'],
|
|
97
|
+
'timeline' => @timeline_name,
|
|
98
|
+
'id' => activity.start
|
|
99
|
+
})
|
|
100
|
+
hostname = ENV['OPENC3_SCRIPT_HOSTNAME'] || 'openc3-script-runner-api'
|
|
101
|
+
response = Net::HTTP.new(hostname, 2902).request(request)
|
|
102
|
+
raise "failed to call #{hostname}, for script: #{activity.data['script']}, response code: #{response.code}" if response.code != '200'
|
|
103
|
+
|
|
104
|
+
activity.commit(status: 'completed', message: "#{activity.data['script']} => #{response.body}", fulfillment: true)
|
|
105
|
+
rescue StandardError => e
|
|
106
|
+
activity.commit(status: 'failed', message: e.message)
|
|
107
|
+
Logger.error "#{@timeline_name} run_script failed > #{activity.as_json(:allow_nan => true).to_s}, #{e.message}"
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def clear_expired(activity)
|
|
112
|
+
begin
|
|
113
|
+
ActivityModel.range_destroy(name: @timeline_name, scope: @scope, min: activity.start, max: activity.stop)
|
|
114
|
+
activity.add_event(status: 'completed')
|
|
115
|
+
rescue StandardError => e
|
|
116
|
+
Logger.error "#{@timeline_name} clear_expired failed > #{activity.as_json(:allow_nan => true)} #{e.message}"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Shared between the monitor thread and the manager thread to
|
|
122
|
+
# share the planned activities. This should remain a thread
|
|
123
|
+
# safe implamentation.
|
|
124
|
+
class Schedule
|
|
125
|
+
def initialize(name)
|
|
126
|
+
@name = name
|
|
127
|
+
@activities_mutex = Mutex.new
|
|
128
|
+
@activities = []
|
|
129
|
+
@size = 20
|
|
130
|
+
@queue = Array.new(@size)
|
|
131
|
+
@index = 0
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def not_queued?(start)
|
|
135
|
+
return false if @queue.index(start)
|
|
136
|
+
|
|
137
|
+
@queue[@index] = start
|
|
138
|
+
@index = @index + 1 >= @size ? 0 : @index + 1
|
|
139
|
+
return true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def activities
|
|
143
|
+
@activities_mutex.synchronize do
|
|
144
|
+
return @activities.dup
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def update(input_activities)
|
|
149
|
+
@activities_mutex.synchronize do
|
|
150
|
+
@activities = input_activities.dup
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def add_activity(input_activity)
|
|
155
|
+
@activities_mutex.synchronize do
|
|
156
|
+
if @activities.find { |x| x.start == input_activity.start }.nil?
|
|
157
|
+
@activities << input_activity
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def remove_activity(input_activity)
|
|
163
|
+
@activities_mutex.synchronize do
|
|
164
|
+
@activities.delete_if { |h| h.start == input_activity.start }
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# The timeline manager starts a thread pool and looks at the
|
|
170
|
+
# schedule and if an "activity" should be run. TimelineManager
|
|
171
|
+
# adds the "activity" to the thread pool and the thread will
|
|
172
|
+
# execute the "activity".
|
|
173
|
+
class TimelineManager
|
|
174
|
+
def initialize(name:, scope:, schedule:)
|
|
175
|
+
@timeline_name = name
|
|
176
|
+
@scope = scope
|
|
177
|
+
@schedule = schedule
|
|
178
|
+
@worker_count = 3
|
|
179
|
+
@queue = Queue.new
|
|
180
|
+
@thread_pool = generate_thread_pool()
|
|
181
|
+
@cancel_thread = false
|
|
182
|
+
@expire = 0
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def generate_thread_pool
|
|
186
|
+
thread_pool = []
|
|
187
|
+
@worker_count.times {
|
|
188
|
+
worker = TimelineWorker.new(name: @timeline_name, scope: @scope, queue: @queue)
|
|
189
|
+
thread_pool << Thread.new { worker.run }
|
|
190
|
+
}
|
|
191
|
+
return thread_pool
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def run
|
|
195
|
+
Logger.info "#{@timeline_name} timeline manager running"
|
|
196
|
+
loop do
|
|
197
|
+
start = Time.now.to_i
|
|
198
|
+
@schedule.activities.each do |activity|
|
|
199
|
+
start_difference = activity.start - start
|
|
200
|
+
if start_difference <= 0 && @schedule.not_queued?(activity.start)
|
|
201
|
+
Logger.debug "#{@timeline_name} #{@scope} current start: #{start}, vs #{activity.start}, #{start_difference}"
|
|
202
|
+
activity.add_event(status: 'queued')
|
|
203
|
+
@queue << activity
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
if start >= @expire
|
|
207
|
+
add_expire_activity()
|
|
208
|
+
request_update(start: start)
|
|
209
|
+
end
|
|
210
|
+
break if @cancel_thread
|
|
211
|
+
|
|
212
|
+
sleep(1)
|
|
213
|
+
break if @cancel_thread
|
|
214
|
+
end
|
|
215
|
+
Logger.info "#{@timeline_name} timeine manager exiting"
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Add task to remove events older than 7 time
|
|
219
|
+
def add_expire_activity
|
|
220
|
+
now = Time.now.to_i
|
|
221
|
+
@expire = now + 3_000
|
|
222
|
+
activity = ActivityModel.new(
|
|
223
|
+
name: @timeline_name,
|
|
224
|
+
scope: @scope,
|
|
225
|
+
start: (now - 86_400 * 7),
|
|
226
|
+
stop: (now - 82_800 * 7),
|
|
227
|
+
kind: 'EXPIRE',
|
|
228
|
+
data: {}
|
|
229
|
+
)
|
|
230
|
+
@queue << activity
|
|
231
|
+
return activity
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# This can feedback to ensure the schedule will not run out so this should fire once an
|
|
235
|
+
# hour to make sure the TimelineMicroservice will collect the next hour and update the
|
|
236
|
+
# schedule.
|
|
237
|
+
def request_update(start:)
|
|
238
|
+
notification = {
|
|
239
|
+
'data' => JSON.generate({ 'time' => start }),
|
|
240
|
+
'kind' => 'refresh',
|
|
241
|
+
'type' => 'timeline',
|
|
242
|
+
'timeline' => @timeline_name
|
|
243
|
+
}
|
|
244
|
+
begin
|
|
245
|
+
TimelineTopic.write_activity(notification, scope: @scope)
|
|
246
|
+
rescue StandardError
|
|
247
|
+
Logger.error "#{@name} manager failed to request update"
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def shutdown
|
|
252
|
+
@cancel_thread = true
|
|
253
|
+
@worker_count.times {
|
|
254
|
+
@queue << nil
|
|
255
|
+
}
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# The timeline microservice starts a manager then gets the activities
|
|
260
|
+
# from the sorted set in redis and updates the schedule for the
|
|
261
|
+
# manager. Timeline will then wait for an update on the timeline
|
|
262
|
+
# stream this will trigger an update again to the schedule.
|
|
263
|
+
class TimelineMicroservice < Microservice
|
|
264
|
+
TIMELINE_METRIC_NAME = 'timeline_activities_duration_seconds'.freeze
|
|
265
|
+
|
|
266
|
+
def initialize(name)
|
|
267
|
+
super(name)
|
|
268
|
+
@timeline_name = name.split('__')[2]
|
|
269
|
+
@schedule = Schedule.new(@timeline_name)
|
|
270
|
+
@manager = TimelineManager.new(name: @timeline_name, scope: scope, schedule: @schedule)
|
|
271
|
+
@manager_thread = nil
|
|
272
|
+
@read_topic = true
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def run
|
|
276
|
+
Logger.info "#{@name} timeine running"
|
|
277
|
+
@manager_thread = Thread.new { @manager.run }
|
|
278
|
+
loop do
|
|
279
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
280
|
+
current_activities = ActivityModel.activities(name: @timeline_name, scope: @scope)
|
|
281
|
+
@schedule.update(current_activities)
|
|
282
|
+
diff = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # seconds as a float
|
|
283
|
+
metric_labels = { 'timeline' => @timeline_name, 'thread' => 'microservice' }
|
|
284
|
+
@metric.add_sample(name: TIMELINE_METRIC_NAME, value: diff, labels: metric_labels)
|
|
285
|
+
break if @cancel_thread
|
|
286
|
+
|
|
287
|
+
block_for_updates()
|
|
288
|
+
break if @cancel_thread
|
|
289
|
+
end
|
|
290
|
+
Logger.info "#{@name} timeine exitting"
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def topic_lookup_functions
|
|
294
|
+
{
|
|
295
|
+
'timeline' => {
|
|
296
|
+
'created' => :timeline_nop,
|
|
297
|
+
'refresh' => :schedule_refresh,
|
|
298
|
+
'updated' => :timeline_nop,
|
|
299
|
+
'deleted' => :timeline_nop
|
|
300
|
+
},
|
|
301
|
+
'activity' => {
|
|
302
|
+
'event' => :timeline_nop,
|
|
303
|
+
'created' => :create_activity_from_event,
|
|
304
|
+
'updated' => :schedule_refresh,
|
|
305
|
+
'deleted' => :remove_activity_from_event
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def block_for_updates
|
|
311
|
+
@read_topic = true
|
|
312
|
+
while @read_topic
|
|
313
|
+
begin
|
|
314
|
+
TimelineTopic.read_topics(@topics) do |_topic, _msg_id, msg_hash, _redis|
|
|
315
|
+
if msg_hash['timeline'] == @timeline_name
|
|
316
|
+
data = JSON.parse(msg_hash['data'], :allow_nan => true, :create_additions => true)
|
|
317
|
+
public_send(topic_lookup_functions[msg_hash['type']][msg_hash['kind']], data)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
rescue StandardError => e
|
|
321
|
+
Logger.error "#{@timeline_name} failed to read topics #{@topics}\n#{e.formatted}"
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def timeline_nop(data)
|
|
327
|
+
Logger.debug "#{@name} timeline web socket event: #{data}"
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def schedule_refresh(data)
|
|
331
|
+
Logger.debug "#{@name} timeline web socket schedule refresh: #{data}"
|
|
332
|
+
@read_topic = false
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# Add the activity to the schedule. We don't need to hold the job in memory
|
|
336
|
+
# if it is longer than an hour away. A refresh task will update that.
|
|
337
|
+
def create_activity_from_event(data)
|
|
338
|
+
diff = data['start'] - Time.now.to_i
|
|
339
|
+
return unless (2..3600).include? diff
|
|
340
|
+
|
|
341
|
+
activity = ActivityModel.from_json(data, name: @timeline_name, scope: @scope)
|
|
342
|
+
@schedule.add_activity(activity)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Remove the activity from the schedule. We don't need to remove the activity
|
|
346
|
+
# if it is longer than an hour away. It will be removed from the data.
|
|
347
|
+
def remove_activity_from_event(data)
|
|
348
|
+
diff = data['start'] - Time.now.to_i
|
|
349
|
+
return unless (2..3600).include? diff
|
|
350
|
+
|
|
351
|
+
activity = ActivityModel.from_json(data, name: @timeline_name, scope: @scope)
|
|
352
|
+
@schedule.remove_activity(activity)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def shutdown
|
|
356
|
+
@read_topic = false
|
|
357
|
+
@manager.shutdown
|
|
358
|
+
super
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
OpenC3::TimelineMicroservice.run if __FILE__ == $0
|