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,137 @@
|
|
|
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 'open-uri'
|
|
21
|
+
require 'nokogiri'
|
|
22
|
+
require 'httpclient'
|
|
23
|
+
require 'rubygems'
|
|
24
|
+
require 'rubygems/uninstaller'
|
|
25
|
+
require 'tempfile'
|
|
26
|
+
require 'openc3/utilities/s3'
|
|
27
|
+
require 'openc3/utilities/process_manager'
|
|
28
|
+
require 'openc3/api/api'
|
|
29
|
+
|
|
30
|
+
module OpenC3
|
|
31
|
+
# This class acts like a Model but doesn't inherit from Model because it doesn't
|
|
32
|
+
# actual interact with the Store (Redis). Instead we implement names, get, put
|
|
33
|
+
# and destroy to allow interaction with gem files from the PluginModel and
|
|
34
|
+
# the GemsController.
|
|
35
|
+
class GemModel
|
|
36
|
+
extend Api
|
|
37
|
+
|
|
38
|
+
@@bucket_initialized = false
|
|
39
|
+
|
|
40
|
+
def self.names
|
|
41
|
+
rubys3_client = initialize_bucket()
|
|
42
|
+
gems = []
|
|
43
|
+
rubys3_client.list_objects(bucket: 'gems').contents.each do |object|
|
|
44
|
+
gems << object.key
|
|
45
|
+
end
|
|
46
|
+
gems
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.get(dir, name)
|
|
50
|
+
rubys3_client = initialize_bucket()
|
|
51
|
+
path = File.join(dir, name)
|
|
52
|
+
rubys3_client.get_object(bucket: 'gems', key: name, response_target: path)
|
|
53
|
+
return path
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.put(gem_file_path, gem_install: true, scope:)
|
|
57
|
+
rubys3_client = initialize_bucket()
|
|
58
|
+
if File.file?(gem_file_path)
|
|
59
|
+
gem_filename = File.basename(gem_file_path)
|
|
60
|
+
Logger.info "Installing gem: #{gem_filename}"
|
|
61
|
+
File.open(gem_file_path, 'rb') do |file|
|
|
62
|
+
rubys3_client.put_object(bucket: 'gems', key: gem_filename, body: file)
|
|
63
|
+
end
|
|
64
|
+
if gem_install
|
|
65
|
+
result = OpenC3::ProcessManager.instance.spawn(["ruby", "/openc3/bin/openc3cli", "geminstall", gem_filename], "gem_install", gem_filename, Time.now + 3600.0, scope: scope)
|
|
66
|
+
return result
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
message = "Gem file #{gem_file_path} does not exist!"
|
|
70
|
+
Logger.error message
|
|
71
|
+
raise message
|
|
72
|
+
end
|
|
73
|
+
return nil
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.install(name_or_path, scope:)
|
|
77
|
+
temp_dir = Dir.mktmpdir
|
|
78
|
+
begin
|
|
79
|
+
if File.exist?(name_or_path)
|
|
80
|
+
gem_file_path = name_or_path
|
|
81
|
+
else
|
|
82
|
+
gem_file_path = get(temp_dir, name_or_path)
|
|
83
|
+
end
|
|
84
|
+
begin
|
|
85
|
+
rubygems_url = get_setting('rubygems_url', scope: scope)
|
|
86
|
+
rescue
|
|
87
|
+
# If Redis isn't running try the ENV, then simply rubygems.org
|
|
88
|
+
rubygems_url = ENV['RUBYGEMS_URL']
|
|
89
|
+
rubygems_url ||= 'https://rubygems.org'
|
|
90
|
+
end
|
|
91
|
+
Gem.sources = [rubygems_url] if rubygems_url
|
|
92
|
+
Gem.done_installing_hooks.clear
|
|
93
|
+
Gem.install(gem_file_path, "> 0.pre", :build_args => ['--no-document'], :prerelease => true)
|
|
94
|
+
rescue => err
|
|
95
|
+
message = "Gem file #{gem_file_path} error installing to /gems\n#{err.formatted}"
|
|
96
|
+
Logger.error message
|
|
97
|
+
ensure
|
|
98
|
+
FileUtils.remove_entry(temp_dir) if temp_dir and File.exist?(temp_dir)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self.destroy(name)
|
|
103
|
+
rubys3_client = initialize_bucket()
|
|
104
|
+
Logger.info "Removing gem: #{name}"
|
|
105
|
+
rubys3_client.delete_object(bucket: 'gems', key: name)
|
|
106
|
+
gem_name, version = self.extract_name_and_version(name)
|
|
107
|
+
begin
|
|
108
|
+
Gem::Uninstaller.new(gem_name, {:version => version, :force => true}).uninstall
|
|
109
|
+
rescue => err
|
|
110
|
+
message = "Gem file #{name} error uninstalling\n#{err.formatted}"
|
|
111
|
+
Logger.error message
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.extract_name_and_version(name)
|
|
116
|
+
split_name = name.split('-')
|
|
117
|
+
gem_name = split_name[0..-2].join('-')
|
|
118
|
+
version = split_name[-1]
|
|
119
|
+
return gem_name, version
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# private
|
|
123
|
+
|
|
124
|
+
def self.initialize_bucket
|
|
125
|
+
rubys3_client = Aws::S3::Client.new
|
|
126
|
+
unless @@bucket_initialized
|
|
127
|
+
begin
|
|
128
|
+
rubys3_client.head_bucket(bucket: 'gems')
|
|
129
|
+
rescue Aws::S3::Errors::NotFound
|
|
130
|
+
rubys3_client.create_bucket(bucket: 'gems')
|
|
131
|
+
end
|
|
132
|
+
@@bucket_initialized = true
|
|
133
|
+
end
|
|
134
|
+
return rubys3_client
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
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/store'
|
|
21
|
+
|
|
22
|
+
module OpenC3
|
|
23
|
+
class InfoModel
|
|
24
|
+
|
|
25
|
+
# @return Hash information and statistics about the redis server
|
|
26
|
+
def self.get()
|
|
27
|
+
return [Store.info(), EphemeralStore.info]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,281 @@
|
|
|
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/models/model'
|
|
21
|
+
require 'openc3/models/microservice_model'
|
|
22
|
+
|
|
23
|
+
module OpenC3
|
|
24
|
+
class InterfaceModel < Model
|
|
25
|
+
INTERFACES_PRIMARY_KEY = 'openc3_interfaces'
|
|
26
|
+
ROUTERS_PRIMARY_KEY = 'openc3_routers'
|
|
27
|
+
|
|
28
|
+
attr_accessor :config_params
|
|
29
|
+
attr_accessor :target_names
|
|
30
|
+
attr_accessor :connect_on_startup
|
|
31
|
+
attr_accessor :auto_reconnect
|
|
32
|
+
attr_accessor :reconnect_delay
|
|
33
|
+
attr_accessor :disable_disconnect
|
|
34
|
+
attr_accessor :options
|
|
35
|
+
attr_accessor :protocols
|
|
36
|
+
attr_accessor :interfaces
|
|
37
|
+
attr_accessor :log
|
|
38
|
+
attr_accessor :log_raw
|
|
39
|
+
attr_accessor :needs_dependencies
|
|
40
|
+
|
|
41
|
+
# NOTE: The following three class methods are used by the ModelController
|
|
42
|
+
# and are reimplemented to enable various Model class methods to work
|
|
43
|
+
def self.get(name:, scope:)
|
|
44
|
+
super("#{scope}__#{_get_key}", name: name)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.names(scope:)
|
|
48
|
+
super("#{scope}__#{_get_key}")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.all(scope:)
|
|
52
|
+
super("#{scope}__#{_get_key}")
|
|
53
|
+
end
|
|
54
|
+
# END NOTE
|
|
55
|
+
|
|
56
|
+
# Called by the PluginModel to allow this class to validate it's top-level keyword: "INTERFACE"
|
|
57
|
+
# Interface/Router specific keywords are handled by the instance method "handle_config"
|
|
58
|
+
# NOTE: See RouterModel for the router method implementation
|
|
59
|
+
def self.handle_config(parser, keyword, parameters, plugin: nil, needs_dependencies: false, scope:)
|
|
60
|
+
case keyword
|
|
61
|
+
when 'INTERFACE'
|
|
62
|
+
parser.verify_num_parameters(2, nil, "INTERFACE <Name> <Filename> <Specific Parameters>")
|
|
63
|
+
return self.new(name: parameters[0].upcase, config_params: parameters[1..-1], plugin: plugin, needs_dependencies: needs_dependencies, scope: scope)
|
|
64
|
+
else
|
|
65
|
+
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Interface: #{keyword} #{parameters.join(" ")}")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Helper method to return the correct type based on class name
|
|
70
|
+
def self._get_type
|
|
71
|
+
self.name.to_s.split("Model")[0].upcase.split("::")[-1]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Helper method to return the correct primary key based on class name
|
|
75
|
+
def self._get_key
|
|
76
|
+
type = _get_type
|
|
77
|
+
case type
|
|
78
|
+
when 'INTERFACE'
|
|
79
|
+
INTERFACES_PRIMARY_KEY
|
|
80
|
+
when 'ROUTER'
|
|
81
|
+
ROUTERS_PRIMARY_KEY
|
|
82
|
+
else
|
|
83
|
+
raise "Unknown type #{type} from class #{self.name}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def initialize(
|
|
88
|
+
name:,
|
|
89
|
+
config_params: [],
|
|
90
|
+
target_names: [],
|
|
91
|
+
connect_on_startup: true,
|
|
92
|
+
auto_reconnect: true,
|
|
93
|
+
reconnect_delay: 5.0,
|
|
94
|
+
disable_disconnect: false,
|
|
95
|
+
options: [],
|
|
96
|
+
protocols: [],
|
|
97
|
+
log: true,
|
|
98
|
+
log_raw: false,
|
|
99
|
+
updated_at: nil,
|
|
100
|
+
plugin: nil,
|
|
101
|
+
needs_dependencies: false,
|
|
102
|
+
scope:
|
|
103
|
+
)
|
|
104
|
+
if self.class._get_type == 'INTERFACE'
|
|
105
|
+
super("#{scope}__#{INTERFACES_PRIMARY_KEY}", name: name, updated_at: updated_at, plugin: plugin, scope: scope)
|
|
106
|
+
else
|
|
107
|
+
super("#{scope}__#{ROUTERS_PRIMARY_KEY}", name: name, updated_at: updated_at, plugin: plugin, scope: scope)
|
|
108
|
+
end
|
|
109
|
+
@config_params = config_params
|
|
110
|
+
@target_names = target_names
|
|
111
|
+
@connect_on_startup = connect_on_startup
|
|
112
|
+
@auto_reconnect = auto_reconnect
|
|
113
|
+
@reconnect_delay = reconnect_delay
|
|
114
|
+
@disable_disconnect = disable_disconnect
|
|
115
|
+
@options = options
|
|
116
|
+
@protocols = protocols
|
|
117
|
+
@log = log
|
|
118
|
+
@log_raw = log_raw
|
|
119
|
+
@needs_dependencies = needs_dependencies
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Called by InterfaceMicroservice to instantiate the Interface defined
|
|
123
|
+
# by the model configuration. Must be called after get_model which
|
|
124
|
+
# calls from_json to instantiate the class and populate the attributes.
|
|
125
|
+
def build
|
|
126
|
+
klass = OpenC3.require_class(@config_params[0])
|
|
127
|
+
if @config_params.length > 1
|
|
128
|
+
interface_or_router = klass.new(*@config_params[1..-1])
|
|
129
|
+
else
|
|
130
|
+
interface_or_router = klass.new
|
|
131
|
+
end
|
|
132
|
+
interface_or_router.target_names = @target_names.dup
|
|
133
|
+
interface_or_router.connect_on_startup = @connect_on_startup
|
|
134
|
+
interface_or_router.auto_reconnect = @auto_reconnect
|
|
135
|
+
interface_or_router.reconnect_delay = @reconnect_delay
|
|
136
|
+
interface_or_router.disable_disconnect = @disable_disconnect
|
|
137
|
+
@options.each do |option|
|
|
138
|
+
interface_or_router.set_option(option[0], option[1..-1])
|
|
139
|
+
end
|
|
140
|
+
@protocols.each do |protocol|
|
|
141
|
+
klass = OpenC3.require_class(protocol[1])
|
|
142
|
+
interface_or_router.add_protocol(klass, protocol[2..-1], protocol[0].upcase.intern)
|
|
143
|
+
end
|
|
144
|
+
interface_or_router
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def as_json(*a)
|
|
148
|
+
{
|
|
149
|
+
'name' => @name,
|
|
150
|
+
'config_params' => @config_params,
|
|
151
|
+
'target_names' => @target_names,
|
|
152
|
+
'connect_on_startup' => @connect_on_startup,
|
|
153
|
+
'auto_reconnect' => @auto_reconnect,
|
|
154
|
+
'reconnect_delay' => @reconnect_delay,
|
|
155
|
+
'disable_disconnect' => @disable_disconnect,
|
|
156
|
+
'options' => @options,
|
|
157
|
+
'protocols' => @protocols,
|
|
158
|
+
'log' => @log,
|
|
159
|
+
'log_raw' => @log_raw,
|
|
160
|
+
'plugin' => @plugin,
|
|
161
|
+
'needs_dependencies' => @needs_dependencies,
|
|
162
|
+
'updated_at' => @updated_at
|
|
163
|
+
}
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# TODO: Not currently used but may be used by a XTCE or other format to OpenC3 conversion
|
|
167
|
+
def as_config
|
|
168
|
+
result = "#{self.class._get_type} #{@name} #{@config_params.join(' ')}\n"
|
|
169
|
+
@target_names.each do |target_name|
|
|
170
|
+
result << " MAP_TARGET #{target_name}\n"
|
|
171
|
+
end
|
|
172
|
+
result << " DONT_CONNECT\n" unless @connect_on_startup
|
|
173
|
+
result << " DONT_RECONNECT\n" unless @auto_reconnect
|
|
174
|
+
result << " RECONNECT_DELAY #{@reconnect_delay}\n"
|
|
175
|
+
result << " DISABLE_DISCONNECT\n" if @disable_disconnect
|
|
176
|
+
@options.each do |option|
|
|
177
|
+
result << " OPTION #{option.join(' ')}\n"
|
|
178
|
+
end
|
|
179
|
+
@protocols.each do |protocol|
|
|
180
|
+
result << " PROTOCOL #{protocol.join(' ')}\n"
|
|
181
|
+
end
|
|
182
|
+
result << " DONT_LOG" unless @log
|
|
183
|
+
result << " LOG_RAW" if @log_raw
|
|
184
|
+
result
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Handles Interface/Router specific configuration keywords
|
|
188
|
+
def handle_config(parser, keyword, parameters)
|
|
189
|
+
case keyword
|
|
190
|
+
when 'MAP_TARGET'
|
|
191
|
+
parser.verify_num_parameters(1, 1, "#{keyword} <Target Name>")
|
|
192
|
+
@target_names << parameters[0].upcase
|
|
193
|
+
|
|
194
|
+
when 'DONT_CONNECT'
|
|
195
|
+
parser.verify_num_parameters(0, 0, "#{keyword}")
|
|
196
|
+
@connect_on_startup = false
|
|
197
|
+
|
|
198
|
+
when 'DONT_RECONNECT'
|
|
199
|
+
parser.verify_num_parameters(0, 0, "#{keyword}")
|
|
200
|
+
@auto_reconnect = false
|
|
201
|
+
|
|
202
|
+
when 'RECONNECT_DELAY'
|
|
203
|
+
parser.verify_num_parameters(1, 1, "#{keyword} <Delay in Seconds>")
|
|
204
|
+
@reconnect_delay = Float(parameters[0])
|
|
205
|
+
|
|
206
|
+
when 'DISABLE_DISCONNECT'
|
|
207
|
+
parser.verify_num_parameters(0, 0, "#{keyword}")
|
|
208
|
+
@disable_disconnect = true
|
|
209
|
+
|
|
210
|
+
when 'OPTION'
|
|
211
|
+
parser.verify_num_parameters(2, nil, "#{keyword} <Option Name> <Option Value 1> <Option Value 2 (optional)> <etc>")
|
|
212
|
+
@options << parameters.dup
|
|
213
|
+
|
|
214
|
+
when 'PROTOCOL'
|
|
215
|
+
usage = "#{keyword} <READ WRITE READ_WRITE> <protocol filename or classname> <Protocol specific parameters>"
|
|
216
|
+
parser.verify_num_parameters(2, nil, usage)
|
|
217
|
+
unless %w(READ WRITE READ_WRITE).include? parameters[0].upcase
|
|
218
|
+
raise parser.error("Invalid protocol type: #{parameters[0]}", usage)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
@protocols << parameters.dup
|
|
222
|
+
|
|
223
|
+
when 'DONT_LOG'
|
|
224
|
+
parser.verify_num_parameters(0, 0, "#{keyword}")
|
|
225
|
+
@log = false
|
|
226
|
+
|
|
227
|
+
when 'LOG_RAW'
|
|
228
|
+
parser.verify_num_parameters(0, 0, "#{keyword}")
|
|
229
|
+
@log_raw = true
|
|
230
|
+
|
|
231
|
+
else
|
|
232
|
+
raise ConfigParser::Error.new(parser, "Unknown keyword and parameters for Interface/Router: #{keyword} #{parameters.join(" ")}")
|
|
233
|
+
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
return nil
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Creates a MicroserviceModel to deploy the Interface/Router
|
|
240
|
+
def deploy(gem_path, variables, validate_only: false)
|
|
241
|
+
type = self.class._get_type
|
|
242
|
+
microservice_name = "#{@scope}__#{type}__#{@name}"
|
|
243
|
+
microservice = MicroserviceModel.new(
|
|
244
|
+
name: microservice_name,
|
|
245
|
+
work_dir: '/openc3/lib/openc3/microservices',
|
|
246
|
+
cmd: ["ruby", "#{type.downcase}_microservice.rb", microservice_name],
|
|
247
|
+
target_names: @target_names,
|
|
248
|
+
plugin: @plugin,
|
|
249
|
+
needs_dependencies: @needs_dependencies,
|
|
250
|
+
scope: @scope
|
|
251
|
+
)
|
|
252
|
+
unless validate_only
|
|
253
|
+
microservice.create
|
|
254
|
+
microservice.deploy(gem_path, variables)
|
|
255
|
+
ConfigTopic.write({ kind: 'created', type: type.downcase, name: @name, plugin: @plugin }, scope: @scope)
|
|
256
|
+
Logger.info "Configured #{type.downcase} microservice #{microservice_name}"
|
|
257
|
+
end
|
|
258
|
+
microservice
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Looks up the deployed MicroserviceModel and destroy the microservice model
|
|
262
|
+
# should should trigger the operator to kill the microservice that in turn
|
|
263
|
+
# will destroy the InterfaceStatusModel when a stop is called.
|
|
264
|
+
def undeploy
|
|
265
|
+
type = self.class._get_type
|
|
266
|
+
name = "#{@scope}__#{type}__#{@name}"
|
|
267
|
+
model = MicroserviceModel.get_model(name: name, scope: @scope)
|
|
268
|
+
if model
|
|
269
|
+
model.destroy
|
|
270
|
+
ConfigTopic.write({ kind: 'deleted', type: type.downcase, name: @name, plugin: @plugin }, scope: @scope)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
if type == 'INTERFACE'
|
|
274
|
+
status_model = InterfaceStatusModel.get_model(name: @name, scope: @scope)
|
|
275
|
+
else
|
|
276
|
+
status_model = RouterStatusModel.get_model(name: @name, scope: @scope)
|
|
277
|
+
end
|
|
278
|
+
status_model.destroy if status_model
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
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/models/model'
|
|
21
|
+
|
|
22
|
+
module OpenC3
|
|
23
|
+
# Stores the status about an interface. This class also implements logic
|
|
24
|
+
# to handle status for a router since the functionality is identical
|
|
25
|
+
# (only difference is the Redis key used).
|
|
26
|
+
class InterfaceStatusModel < EphemeralModel
|
|
27
|
+
INTERFACES_PRIMARY_KEY = 'openc3_interface_status'
|
|
28
|
+
ROUTERS_PRIMARY_KEY = 'openc3_router_status'
|
|
29
|
+
|
|
30
|
+
attr_accessor :state
|
|
31
|
+
attr_accessor :clients
|
|
32
|
+
attr_accessor :txsize
|
|
33
|
+
attr_accessor :rxsize
|
|
34
|
+
attr_accessor :txbytes
|
|
35
|
+
attr_accessor :rxbytes
|
|
36
|
+
attr_accessor :txcnt
|
|
37
|
+
attr_accessor :rxcnt
|
|
38
|
+
|
|
39
|
+
# NOTE: The following three class methods are used by the ModelController
|
|
40
|
+
# and are reimplemented to enable various Model class methods to work
|
|
41
|
+
def self.get(name:, scope:)
|
|
42
|
+
super("#{scope}__#{_get_key}", name: name)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.names(scope:)
|
|
46
|
+
super("#{scope}__#{_get_key}")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.all(scope:)
|
|
50
|
+
super("#{scope}__#{_get_key}")
|
|
51
|
+
end
|
|
52
|
+
# END NOTE
|
|
53
|
+
|
|
54
|
+
# Helper method to return the correct type based on class name
|
|
55
|
+
def self._get_type
|
|
56
|
+
self.name.to_s.split("Model")[0].upcase.split("::")[-1]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Helper method to return the correct primary key based on class name
|
|
60
|
+
def self._get_key
|
|
61
|
+
type = _get_type
|
|
62
|
+
case type
|
|
63
|
+
when 'INTERFACESTATUS'
|
|
64
|
+
INTERFACES_PRIMARY_KEY
|
|
65
|
+
when 'ROUTERSTATUS'
|
|
66
|
+
ROUTERS_PRIMARY_KEY
|
|
67
|
+
else
|
|
68
|
+
raise "Unknown type #{type} from class #{self.name}"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def initialize(
|
|
73
|
+
name:,
|
|
74
|
+
state:,
|
|
75
|
+
clients: 0,
|
|
76
|
+
txsize: 0,
|
|
77
|
+
rxsize: 0,
|
|
78
|
+
txbytes: 0,
|
|
79
|
+
rxbytes: 0,
|
|
80
|
+
txcnt: 0,
|
|
81
|
+
rxcnt: 0,
|
|
82
|
+
updated_at: nil,
|
|
83
|
+
plugin: nil,
|
|
84
|
+
scope:
|
|
85
|
+
)
|
|
86
|
+
if self.class._get_type == 'INTERFACESTATUS'
|
|
87
|
+
super("#{scope}__#{INTERFACES_PRIMARY_KEY}", name: name, updated_at: updated_at, plugin: plugin, scope: scope)
|
|
88
|
+
else
|
|
89
|
+
super("#{scope}__#{ROUTERS_PRIMARY_KEY}", name: name, updated_at: updated_at, plugin: plugin, scope: scope)
|
|
90
|
+
end
|
|
91
|
+
@state = state
|
|
92
|
+
@clients = clients
|
|
93
|
+
@txsize = txsize
|
|
94
|
+
@rxsize = rxsize
|
|
95
|
+
@txbytes = txbytes
|
|
96
|
+
@rxbytes = rxbytes
|
|
97
|
+
@txcnt = txcnt
|
|
98
|
+
@rxcnt = rxcnt
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def as_json(*a)
|
|
102
|
+
{
|
|
103
|
+
'name' => @name,
|
|
104
|
+
'state' => @state,
|
|
105
|
+
'clients' => @clients,
|
|
106
|
+
'txsize' => @txsize,
|
|
107
|
+
'rxsize' => @rxsize,
|
|
108
|
+
'txbytes' => @txbytes,
|
|
109
|
+
'rxbytes' => @rxbytes,
|
|
110
|
+
'txcnt' => @txcnt,
|
|
111
|
+
'rxcnt' => @rxcnt,
|
|
112
|
+
'plugin' => @plugin,
|
|
113
|
+
'updated_at' => @updated_at
|
|
114
|
+
}
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
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
|
+
# https://www.rubydoc.info/gems/redis/Redis/Commands/SortedSets
|
|
21
|
+
|
|
22
|
+
require 'openc3/models/sorted_model'
|
|
23
|
+
|
|
24
|
+
module OpenC3
|
|
25
|
+
class MetadataModel < SortedModel
|
|
26
|
+
METADATA_TYPE = 'metadata'.freeze
|
|
27
|
+
PRIMARY_KEY = '__METADATA'.freeze
|
|
28
|
+
|
|
29
|
+
def self.pk(scope)
|
|
30
|
+
"#{scope}#{PRIMARY_KEY}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :color, :metadata, :constraints, :type
|
|
34
|
+
|
|
35
|
+
# @param [Integer] start - Time metadata is active in seconds from Epoch
|
|
36
|
+
# @param [String] color - The event color
|
|
37
|
+
# @param [Hash] metadata - Hash of metadata values
|
|
38
|
+
# @param [Hash] constraints - Constraints to apply to the metadata
|
|
39
|
+
# @param [String] scope - OpenC3 scope to track event to
|
|
40
|
+
def initialize(
|
|
41
|
+
scope:,
|
|
42
|
+
start:,
|
|
43
|
+
color: nil,
|
|
44
|
+
metadata:,
|
|
45
|
+
constraints: nil,
|
|
46
|
+
type: METADATA_TYPE,
|
|
47
|
+
updated_at: 0
|
|
48
|
+
)
|
|
49
|
+
super(start: start, scope: scope, updated_at: updated_at)
|
|
50
|
+
@start = start
|
|
51
|
+
@color = color
|
|
52
|
+
@metadata = metadata
|
|
53
|
+
@constraints = constraints if constraints
|
|
54
|
+
@type = type # For the as_json, from_json round trip
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Validates the instance variables: @start, @color, @metadata
|
|
58
|
+
def validate(update: false)
|
|
59
|
+
validate_start(update: update)
|
|
60
|
+
validate_color()
|
|
61
|
+
validate_metadata()
|
|
62
|
+
validate_constraints() if @constraints
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def validate_color()
|
|
66
|
+
if @color.nil?
|
|
67
|
+
@color = '#%06x' % (rand * 0xffffff)
|
|
68
|
+
end
|
|
69
|
+
unless @color =~ /(#*)([0-9,a-f,A-f]{6})/
|
|
70
|
+
raise SortedInputError.new "invalid color, must be in hex format, e.g. #FF0000"
|
|
71
|
+
end
|
|
72
|
+
@color = "##{@color}" unless @color.start_with?('#')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def validate_metadata()
|
|
76
|
+
unless @metadata.is_a?(Hash)
|
|
77
|
+
raise SortedInputError.new "Metadata must be a hash/object: #{@metadata}"
|
|
78
|
+
end
|
|
79
|
+
# Convert keys to strings. This isn't quite as efficient as symbols
|
|
80
|
+
# but we store as JSON which is all strings and it makes comparisons easier.
|
|
81
|
+
@metadata = @metadata.transform_keys(&:to_s)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def validate_constraints()
|
|
85
|
+
unless @constraints.is_a?(Hash)
|
|
86
|
+
raise SortedInputError.new "Constraints must be a hash/object: #{@constraints}"
|
|
87
|
+
end
|
|
88
|
+
# Convert keys to strings. This isn't quite as efficient as symbols
|
|
89
|
+
# but we store as JSON which is all strings and it makes comparisons easier.
|
|
90
|
+
@constraints = @constraints.transform_keys(&:to_s)
|
|
91
|
+
unless (@constraints.keys - @metadata.keys).empty?
|
|
92
|
+
raise SortedInputError.new "Constraints keys must be subset of metadata: #{@constraints.keys} subset #{@metadata.keys}"
|
|
93
|
+
end
|
|
94
|
+
@constraints.each do |key, constraint|
|
|
95
|
+
unless constraint.include?(@metadata[key])
|
|
96
|
+
raise SortedInputError.new "Constraint violation! key:#{key} value:#{@metadata[key]} constraint:#{constraint}"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Update the Redis hash at primary_key based on the initial passed start
|
|
102
|
+
# The member is set to the JSON generated via calling as_json
|
|
103
|
+
def create(update: false)
|
|
104
|
+
validate(update: update)
|
|
105
|
+
@updated_at = Time.now.to_nsec_from_epoch
|
|
106
|
+
MetadataModel.destroy(scope: @scope, start: update) if update
|
|
107
|
+
Store.zadd(@primary_key, @start, JSON.generate(as_json(:allow_nan => true)))
|
|
108
|
+
if update
|
|
109
|
+
notify(kind: 'updated')
|
|
110
|
+
else
|
|
111
|
+
notify(kind: 'created')
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Update the model. All arguments are optional, only those set will be updated.
|
|
116
|
+
def update(start: nil, color: nil, metadata: nil, constraints: nil)
|
|
117
|
+
orig_start = @start
|
|
118
|
+
@start = start if start
|
|
119
|
+
@color = color if color
|
|
120
|
+
@metadata = metadata if metadata
|
|
121
|
+
@constraints = constraints if constraints
|
|
122
|
+
create(update: orig_start)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# @return [Hash] generated from the MetadataModel
|
|
126
|
+
def as_json(*a)
|
|
127
|
+
{
|
|
128
|
+
'scope' => @scope,
|
|
129
|
+
'start' => @start,
|
|
130
|
+
'color' => @color,
|
|
131
|
+
'metadata' => @metadata.as_json(*a),
|
|
132
|
+
'constraints' => @constraints,
|
|
133
|
+
'type' => METADATA_TYPE,
|
|
134
|
+
'updated_at' => @updated_at,
|
|
135
|
+
}
|
|
136
|
+
end
|
|
137
|
+
alias to_s as_json
|
|
138
|
+
end
|
|
139
|
+
end
|