right_agent 2.0.7-x86-mingw32
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.
- data/LICENSE +20 -0
- data/README.rdoc +82 -0
- data/Rakefile +113 -0
- data/lib/right_agent.rb +59 -0
- data/lib/right_agent/actor.rb +182 -0
- data/lib/right_agent/actor_registry.rb +76 -0
- data/lib/right_agent/actors/agent_manager.rb +232 -0
- data/lib/right_agent/agent.rb +1149 -0
- data/lib/right_agent/agent_config.rb +480 -0
- data/lib/right_agent/agent_identity.rb +210 -0
- data/lib/right_agent/agent_tag_manager.rb +237 -0
- data/lib/right_agent/audit_formatter.rb +107 -0
- data/lib/right_agent/clients.rb +31 -0
- data/lib/right_agent/clients/api_client.rb +383 -0
- data/lib/right_agent/clients/auth_client.rb +247 -0
- data/lib/right_agent/clients/balanced_http_client.rb +369 -0
- data/lib/right_agent/clients/base_retry_client.rb +495 -0
- data/lib/right_agent/clients/right_http_client.rb +279 -0
- data/lib/right_agent/clients/router_client.rb +493 -0
- data/lib/right_agent/command.rb +30 -0
- data/lib/right_agent/command/agent_manager_commands.rb +150 -0
- data/lib/right_agent/command/command_client.rb +136 -0
- data/lib/right_agent/command/command_constants.rb +33 -0
- data/lib/right_agent/command/command_io.rb +126 -0
- data/lib/right_agent/command/command_parser.rb +87 -0
- data/lib/right_agent/command/command_runner.rb +118 -0
- data/lib/right_agent/command/command_serializer.rb +63 -0
- data/lib/right_agent/connectivity_checker.rb +179 -0
- data/lib/right_agent/console.rb +65 -0
- data/lib/right_agent/core_payload_types.rb +44 -0
- data/lib/right_agent/core_payload_types/cookbook.rb +61 -0
- data/lib/right_agent/core_payload_types/cookbook_position.rb +46 -0
- data/lib/right_agent/core_payload_types/cookbook_repository.rb +116 -0
- data/lib/right_agent/core_payload_types/cookbook_sequence.rb +70 -0
- data/lib/right_agent/core_payload_types/dev_repositories.rb +100 -0
- data/lib/right_agent/core_payload_types/dev_repository.rb +76 -0
- data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
- data/lib/right_agent/core_payload_types/executable_bundle.rb +130 -0
- data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
- data/lib/right_agent/core_payload_types/login_user.rb +79 -0
- data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
- data/lib/right_agent/core_payload_types/recipe_instantiation.rb +73 -0
- data/lib/right_agent/core_payload_types/repositories_bundle.rb +50 -0
- data/lib/right_agent/core_payload_types/right_script_attachment.rb +95 -0
- data/lib/right_agent/core_payload_types/right_script_instantiation.rb +94 -0
- data/lib/right_agent/core_payload_types/runlist_policy.rb +44 -0
- data/lib/right_agent/core_payload_types/secure_document.rb +66 -0
- data/lib/right_agent/core_payload_types/secure_document_location.rb +63 -0
- data/lib/right_agent/core_payload_types/software_repository_instantiation.rb +61 -0
- data/lib/right_agent/daemonize.rb +35 -0
- data/lib/right_agent/dispatched_cache.rb +109 -0
- data/lib/right_agent/dispatcher.rb +272 -0
- data/lib/right_agent/enrollment_result.rb +221 -0
- data/lib/right_agent/exceptions.rb +87 -0
- data/lib/right_agent/history.rb +145 -0
- data/lib/right_agent/log.rb +460 -0
- data/lib/right_agent/minimal.rb +46 -0
- data/lib/right_agent/monkey_patches.rb +30 -0
- data/lib/right_agent/monkey_patches/ruby_patch.rb +55 -0
- data/lib/right_agent/monkey_patches/ruby_patch/array_patch.rb +29 -0
- data/lib/right_agent/monkey_patches/ruby_patch/darwin_patch.rb +24 -0
- data/lib/right_agent/monkey_patches/ruby_patch/linux_patch.rb +24 -0
- data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +30 -0
- data/lib/right_agent/monkey_patches/ruby_patch/object_patch.rb +49 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch.rb +32 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +60 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/process_patch.rb +63 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/stdio_patch.rb +27 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/time_patch.rb +55 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/win32ole_patch.rb +34 -0
- data/lib/right_agent/multiplexer.rb +102 -0
- data/lib/right_agent/offline_handler.rb +270 -0
- data/lib/right_agent/operation_result.rb +300 -0
- data/lib/right_agent/packets.rb +673 -0
- data/lib/right_agent/payload_formatter.rb +104 -0
- data/lib/right_agent/pending_requests.rb +128 -0
- data/lib/right_agent/pid_file.rb +159 -0
- data/lib/right_agent/platform.rb +770 -0
- data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
- data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
- data/lib/right_agent/platform/unix/platform.rb +226 -0
- data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
- data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
- data/lib/right_agent/platform/windows/platform.rb +1808 -0
- data/lib/right_agent/protocol_version_mixin.rb +69 -0
- data/lib/right_agent/retryable_request.rb +195 -0
- data/lib/right_agent/scripts/agent_controller.rb +543 -0
- data/lib/right_agent/scripts/agent_deployer.rb +400 -0
- data/lib/right_agent/scripts/common_parser.rb +160 -0
- data/lib/right_agent/scripts/log_level_manager.rb +192 -0
- data/lib/right_agent/scripts/stats_manager.rb +268 -0
- data/lib/right_agent/scripts/usage.rb +58 -0
- data/lib/right_agent/secure_identity.rb +92 -0
- data/lib/right_agent/security.rb +32 -0
- data/lib/right_agent/security/cached_certificate_store_proxy.rb +77 -0
- data/lib/right_agent/security/certificate.rb +102 -0
- data/lib/right_agent/security/certificate_cache.rb +89 -0
- data/lib/right_agent/security/distinguished_name.rb +56 -0
- data/lib/right_agent/security/encrypted_document.rb +83 -0
- data/lib/right_agent/security/rsa_key_pair.rb +76 -0
- data/lib/right_agent/security/signature.rb +86 -0
- data/lib/right_agent/security/static_certificate_store.rb +85 -0
- data/lib/right_agent/sender.rb +792 -0
- data/lib/right_agent/serialize.rb +29 -0
- data/lib/right_agent/serialize/message_pack.rb +107 -0
- data/lib/right_agent/serialize/secure_serializer.rb +151 -0
- data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
- data/lib/right_agent/serialize/serializable.rb +151 -0
- data/lib/right_agent/serialize/serializer.rb +159 -0
- data/lib/right_agent/subprocess.rb +38 -0
- data/lib/right_agent/tracer.rb +124 -0
- data/right_agent.gemspec +101 -0
- data/spec/actor_registry_spec.rb +80 -0
- data/spec/actor_spec.rb +162 -0
- data/spec/agent_config_spec.rb +235 -0
- data/spec/agent_identity_spec.rb +78 -0
- data/spec/agent_spec.rb +734 -0
- data/spec/agent_tag_manager_spec.rb +319 -0
- data/spec/clients/api_client_spec.rb +423 -0
- data/spec/clients/auth_client_spec.rb +272 -0
- data/spec/clients/balanced_http_client_spec.rb +576 -0
- data/spec/clients/base_retry_client_spec.rb +635 -0
- data/spec/clients/router_client_spec.rb +594 -0
- data/spec/clients/spec_helper.rb +111 -0
- data/spec/command/agent_manager_commands_spec.rb +51 -0
- data/spec/command/command_io_spec.rb +93 -0
- data/spec/command/command_parser_spec.rb +79 -0
- data/spec/command/command_runner_spec.rb +107 -0
- data/spec/command/command_serializer_spec.rb +51 -0
- data/spec/connectivity_checker_spec.rb +83 -0
- data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
- data/spec/core_payload_types/dev_repository_spec.rb +33 -0
- data/spec/core_payload_types/executable_bundle_spec.rb +67 -0
- data/spec/core_payload_types/login_user_spec.rb +102 -0
- data/spec/core_payload_types/recipe_instantiation_spec.rb +81 -0
- data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
- data/spec/core_payload_types/right_script_instantiation_spec.rb +79 -0
- data/spec/core_payload_types/spec_helper.rb +23 -0
- data/spec/dispatched_cache_spec.rb +136 -0
- data/spec/dispatcher_spec.rb +324 -0
- data/spec/enrollment_result_spec.rb +53 -0
- data/spec/history_spec.rb +246 -0
- data/spec/log_spec.rb +192 -0
- data/spec/monkey_patches/eventmachine_spec.rb +62 -0
- data/spec/multiplexer_spec.rb +48 -0
- data/spec/offline_handler_spec.rb +340 -0
- data/spec/operation_result_spec.rb +208 -0
- data/spec/packets_spec.rb +461 -0
- data/spec/pending_requests_spec.rb +136 -0
- data/spec/platform/spec_helper.rb +216 -0
- data/spec/platform/unix/darwin/platform_spec.rb +181 -0
- data/spec/platform/unix/linux/platform_spec.rb +540 -0
- data/spec/platform/unix/spec_helper.rb +149 -0
- data/spec/platform/windows/mingw/platform_spec.rb +222 -0
- data/spec/platform/windows/mswin/platform_spec.rb +259 -0
- data/spec/platform/windows/spec_helper.rb +720 -0
- data/spec/retryable_request_spec.rb +306 -0
- data/spec/secure_identity_spec.rb +50 -0
- data/spec/security/cached_certificate_store_proxy_spec.rb +62 -0
- data/spec/security/certificate_cache_spec.rb +71 -0
- data/spec/security/certificate_spec.rb +49 -0
- data/spec/security/distinguished_name_spec.rb +46 -0
- data/spec/security/encrypted_document_spec.rb +55 -0
- data/spec/security/rsa_key_pair_spec.rb +55 -0
- data/spec/security/signature_spec.rb +66 -0
- data/spec/security/static_certificate_store_spec.rb +58 -0
- data/spec/sender_spec.rb +1045 -0
- data/spec/serialize/message_pack_spec.rb +131 -0
- data/spec/serialize/secure_serializer_spec.rb +132 -0
- data/spec/serialize/serializable_spec.rb +90 -0
- data/spec/serialize/serializer_spec.rb +197 -0
- data/spec/spec.opts +2 -0
- data/spec/spec.win32.opts +1 -0
- data/spec/spec_helper.rb +130 -0
- data/spec/tracer_spec.rb +114 -0
- metadata +447 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
|
24
|
+
module RightScale
|
25
|
+
|
26
|
+
class CommandParser
|
27
|
+
|
28
|
+
# Register callback block
|
29
|
+
#
|
30
|
+
# === Block
|
31
|
+
# Block that will get called back whenever a command is successfully parsed
|
32
|
+
#
|
33
|
+
# === Raise
|
34
|
+
# (ArgumentError): If block is missing
|
35
|
+
def initialize &block
|
36
|
+
raise ArgumentError, 'Missing handler block' unless block
|
37
|
+
@callback = block
|
38
|
+
@buildup = ''
|
39
|
+
end
|
40
|
+
|
41
|
+
# Parse given input
|
42
|
+
# May cause multiple callbacks if multiple commands are successfully parsed
|
43
|
+
# Callback happens in next EM tick
|
44
|
+
#
|
45
|
+
# === Parameters
|
46
|
+
# chunk(String):: Chunck of serialized command(s) to be parsed
|
47
|
+
#
|
48
|
+
# === Return
|
49
|
+
# true:: If callback was called at least once
|
50
|
+
# false:: Otherwise
|
51
|
+
def parse_chunk(chunk)
|
52
|
+
@buildup << chunk
|
53
|
+
chunks = @buildup.split(CommandSerializer::SEPARATOR, -1)
|
54
|
+
if do_call = chunks.size > 1
|
55
|
+
commands = []
|
56
|
+
(0..chunks.size - 2).each do |i|
|
57
|
+
begin
|
58
|
+
commands << CommandSerializer.load(chunks[i])
|
59
|
+
rescue Exception => e
|
60
|
+
# log any exceptions caused by serializing individual chunks instead
|
61
|
+
# of halting EM. each command is discrete so we need to keep trying
|
62
|
+
# so long as there are more commands to process (although subsequent
|
63
|
+
# commands may lack context if previous commands failed).
|
64
|
+
Log.error("Failed parsing command chunk", e, :trace)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
commands.each do |cmd|
|
68
|
+
EM.next_tick do
|
69
|
+
begin
|
70
|
+
@callback.call(cmd)
|
71
|
+
rescue Exception => e
|
72
|
+
# log any exceptions raised by callback instead of halting EM.
|
73
|
+
Log.error("Failed executing parsed command", e, :trace)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@buildup = chunks.last
|
78
|
+
end
|
79
|
+
do_call
|
80
|
+
rescue Exception => e
|
81
|
+
# log any other exceptions instead of halting EM.
|
82
|
+
Log.error("Failed parsing command chunk", e, :trace)
|
83
|
+
end
|
84
|
+
|
85
|
+
end # CommandParser
|
86
|
+
|
87
|
+
end # RightScale
|
@@ -0,0 +1,118 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
module RightScale
|
24
|
+
|
25
|
+
# Run commands exposed by an agent.
|
26
|
+
# External processes can send commands through a socket with the specified port.
|
27
|
+
# Command runner accepts connections and unserializes commands using YAML.
|
28
|
+
# Each command is expected to be a hash containing the :name and :options keys.
|
29
|
+
class CommandRunner
|
30
|
+
class << self
|
31
|
+
# (Integer) Port command runner is listening on
|
32
|
+
attr_reader :listen_port
|
33
|
+
|
34
|
+
# (String) Cookie used by command protocol
|
35
|
+
attr_reader :cookie
|
36
|
+
end
|
37
|
+
|
38
|
+
# Start a command runner listening on a local TCP port.
|
39
|
+
#
|
40
|
+
# === Parameters
|
41
|
+
# socket_port(Integer):: Base socket port on which to listen for connection,
|
42
|
+
# increment and retry if port already taken
|
43
|
+
# identity(String):: Agent identity
|
44
|
+
# commands(Hash):: Commands exposed by agent
|
45
|
+
# fiber_pool(NB::FiberPool):: Pool of initialized fibers to be used for executing
|
46
|
+
# received commands in non-blocking fashion
|
47
|
+
#
|
48
|
+
# === Block
|
49
|
+
# If a block is provided, this method will yield after all setup has been completed,
|
50
|
+
# passing its PidFile to the block. This provides a customization hook, e.g. for
|
51
|
+
# changing the pid file's access mode or ownership.
|
52
|
+
#
|
53
|
+
# === Return
|
54
|
+
# cmd_options[:cookie](String):: Command protocol cookie
|
55
|
+
# cmd_options[:listen_port](Integer):: Command server listen port
|
56
|
+
#
|
57
|
+
# === Raise
|
58
|
+
# (Exceptions::Application):: If +start+ has already been called and +stop+ hasn't since
|
59
|
+
def self.start(socket_port, identity, commands, fiber_pool = nil)
|
60
|
+
cmd_options = nil
|
61
|
+
@listen_port = socket_port
|
62
|
+
|
63
|
+
begin
|
64
|
+
CommandIO.instance.listen(socket_port) do |c, conn|
|
65
|
+
begin
|
66
|
+
cmd_cookie = c[:cookie]
|
67
|
+
if cmd_cookie == @cookie
|
68
|
+
cmd_name = c[:name].to_sym
|
69
|
+
if commands.include?(cmd_name)
|
70
|
+
if fiber_pool
|
71
|
+
fiber_pool.spawn { commands[cmd_name].call(c, conn) }
|
72
|
+
else
|
73
|
+
commands[cmd_name].call(c, conn)
|
74
|
+
end
|
75
|
+
else
|
76
|
+
Log.warning("Unknown command '#{cmd_name}', known commands: #{commands.keys.join(', ')}")
|
77
|
+
end
|
78
|
+
else
|
79
|
+
Log.error("Invalid cookie used by command protocol client (#{cmd_cookie})")
|
80
|
+
end
|
81
|
+
rescue Exception => e
|
82
|
+
Log.warning("Command failed (#{e.message}) at\n#{e.backtrace.join("\n")}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
@cookie = AgentIdentity.generate
|
87
|
+
cmd_options = { :listen_port => @listen_port, :cookie => @cookie }
|
88
|
+
# Now update pid file with command port and cookie
|
89
|
+
pid_file = PidFile.new(identity)
|
90
|
+
if pid_file.exists?
|
91
|
+
pid_file.set_command_options(cmd_options)
|
92
|
+
yield(pid_file) if block_given?
|
93
|
+
else
|
94
|
+
Log.warning("Failed to update listen port in PID file - no pid file found for agent with identity #{identity}")
|
95
|
+
end
|
96
|
+
|
97
|
+
Log.info("[setup] Command server started listening on port #{@listen_port}")
|
98
|
+
rescue Exceptions::IO
|
99
|
+
# Port already taken, increment and retry
|
100
|
+
cmd_options = start(socket_port + 1, identity, commands)
|
101
|
+
end
|
102
|
+
|
103
|
+
cmd_options
|
104
|
+
end
|
105
|
+
|
106
|
+
# Stop command runner, cleanup all opened file descriptors and delete pipe
|
107
|
+
#
|
108
|
+
# === Return
|
109
|
+
# true:: If command listener was listening
|
110
|
+
# false:: Otherwise
|
111
|
+
def self.stop
|
112
|
+
CommandIO.instance.stop_listening
|
113
|
+
Log.info("[stop] Command server stopped listening")
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
|
24
|
+
module RightScale
|
25
|
+
|
26
|
+
class CommandSerializer
|
27
|
+
|
28
|
+
# String appended to serialized data to delimit between commands
|
29
|
+
SEPARATOR = "\n#GO\n"
|
30
|
+
|
31
|
+
# Serialize given command so it can be sent to command listener
|
32
|
+
#
|
33
|
+
# === Parameters
|
34
|
+
# command(Object):: Command to serialize
|
35
|
+
#
|
36
|
+
# === Return
|
37
|
+
# data(String):: Corresponding serialized data
|
38
|
+
def self.dump(command)
|
39
|
+
data = YAML::dump(command)
|
40
|
+
data += SEPARATOR
|
41
|
+
end
|
42
|
+
|
43
|
+
# Deserialize command that was previously serialized with +dump+
|
44
|
+
#
|
45
|
+
# === Parameters
|
46
|
+
# data(String):: String containing serialized data
|
47
|
+
#
|
48
|
+
# === Return
|
49
|
+
# command(Object):: Deserialized command
|
50
|
+
#
|
51
|
+
# === Raise
|
52
|
+
# (RightScale::Exceptions::IO): If serialized data is incorrect
|
53
|
+
def self.load(data)
|
54
|
+
command = YAML::load(data)
|
55
|
+
raise RightScale::Exceptions::IO, "Invalid serialized command:\n#{data}" unless command
|
56
|
+
command
|
57
|
+
rescue RightScale::Exceptions::IO
|
58
|
+
raise
|
59
|
+
rescue Exception => e
|
60
|
+
raise RightScale::Exceptions::IO, "Invalid serialized command: #{e.message}\n#{data}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2013 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
module RightScale
|
24
|
+
|
25
|
+
# Broker connectivity checker
|
26
|
+
# Checks connectivity when requested
|
27
|
+
class ConnectivityChecker
|
28
|
+
|
29
|
+
# Minimum number of seconds between restarts of the inactivity timer
|
30
|
+
MIN_RESTART_INACTIVITY_TIMER_INTERVAL = 60
|
31
|
+
|
32
|
+
# Number of seconds to wait for ping response from a RightNet router when checking connectivity
|
33
|
+
PING_TIMEOUT = 30
|
34
|
+
|
35
|
+
# Default maximum number of consecutive ping timeouts before attempt to reconnect
|
36
|
+
MAX_PING_TIMEOUTS = 3
|
37
|
+
|
38
|
+
# (EM::Timer) Timer while waiting for RightNet router ping response
|
39
|
+
attr_accessor :ping_timer
|
40
|
+
|
41
|
+
def initialize(sender, check_interval, ping_stats, exception_stats)
|
42
|
+
@sender = sender
|
43
|
+
@check_interval = check_interval
|
44
|
+
@ping_timeouts = {}
|
45
|
+
@ping_timer = nil
|
46
|
+
@ping_stats = ping_stats
|
47
|
+
@exception_stats = exception_stats
|
48
|
+
@last_received = Time.now
|
49
|
+
@message_received_callbacks = []
|
50
|
+
restart_inactivity_timer if @check_interval > 0
|
51
|
+
end
|
52
|
+
|
53
|
+
# Update the time this agent last received a request or response message
|
54
|
+
# and restart the inactivity timer thus deferring the next connectivity check
|
55
|
+
# Also forward this message receipt notification to any callbacks that have registered
|
56
|
+
#
|
57
|
+
# === Block
|
58
|
+
# Optional block without parameters that is activated when a message is received
|
59
|
+
#
|
60
|
+
# === Return
|
61
|
+
# true:: Always return true
|
62
|
+
def message_received(&callback)
|
63
|
+
if block_given?
|
64
|
+
@message_received_callbacks << callback
|
65
|
+
else
|
66
|
+
@message_received_callbacks.each { |c| c.call }
|
67
|
+
if @check_interval > 0
|
68
|
+
now = Time.now
|
69
|
+
if (now - @last_received) > MIN_RESTART_INACTIVITY_TIMER_INTERVAL
|
70
|
+
@last_received = now
|
71
|
+
restart_inactivity_timer
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
# Check whether broker connection is usable by pinging a router via that broker
|
79
|
+
# Attempt to reconnect if ping does not respond in PING_TIMEOUT seconds and
|
80
|
+
# if have reached timeout limit
|
81
|
+
# Ignore request if already checking a connection
|
82
|
+
#
|
83
|
+
# === Parameters
|
84
|
+
# id(String):: Identity of specific broker to use to send ping, defaults to any
|
85
|
+
# currently connected broker
|
86
|
+
# max_ping_timeouts(Integer):: Maximum number of ping timeouts before attempt
|
87
|
+
# to reconnect, defaults to MAX_PING_TIMEOUTS
|
88
|
+
#
|
89
|
+
# === Return
|
90
|
+
# true:: Always return true
|
91
|
+
def check(id = nil, max_ping_timeouts = MAX_PING_TIMEOUTS)
|
92
|
+
unless @terminating || @ping_timer || (id && !@sender.client.connected?(id))
|
93
|
+
@ping_id = id
|
94
|
+
@ping_timer = EM::Timer.new(PING_TIMEOUT) do
|
95
|
+
if @ping_id
|
96
|
+
begin
|
97
|
+
@ping_stats.update("timeout")
|
98
|
+
@ping_timer = nil
|
99
|
+
@ping_timeouts[@ping_id] = (@ping_timeouts[@ping_id] || 0) + 1
|
100
|
+
if @ping_timeouts[@ping_id] >= max_ping_timeouts
|
101
|
+
Log.error("Mapper ping via broker #{@ping_id} timed out after #{PING_TIMEOUT} seconds and now " +
|
102
|
+
"reached maximum of #{max_ping_timeouts} timeout#{max_ping_timeouts > 1 ? 's' : ''}, " +
|
103
|
+
"attempting to reconnect")
|
104
|
+
host, port, index, priority = @sender.client.identity_parts(@ping_id)
|
105
|
+
@sender.agent.connect(host, port, index, priority, force = true)
|
106
|
+
else
|
107
|
+
Log.warning("Mapper ping via broker #{@ping_id} timed out after #{PING_TIMEOUT} seconds")
|
108
|
+
end
|
109
|
+
rescue Exception => e
|
110
|
+
Log.error("Failed to reconnect to broker #{@ping_id}", e, :trace)
|
111
|
+
@exception_stats.track("ping timeout", e)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
@ping_timer = nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
handler = lambda do |_|
|
119
|
+
begin
|
120
|
+
if @ping_timer
|
121
|
+
@ping_stats.update("success")
|
122
|
+
@ping_timer.cancel
|
123
|
+
@ping_timer = nil
|
124
|
+
@ping_timeouts[@ping_id] = 0
|
125
|
+
@ping_id = nil
|
126
|
+
end
|
127
|
+
rescue Exception => e
|
128
|
+
Log.error("Failed to cancel router ping", e, :trace)
|
129
|
+
@exception_stats.track("cancel ping", e)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
request = Request.new("/router/ping", nil, {:from => @sender.identity, :token => AgentIdentity.generate})
|
133
|
+
@sender.pending_requests[request.token] = PendingRequest.new(Request, Time.now, handler)
|
134
|
+
ids = [@ping_id] if @ping_id
|
135
|
+
@ping_id = @sender.send(:publish, request, ids).first
|
136
|
+
end
|
137
|
+
true
|
138
|
+
end
|
139
|
+
|
140
|
+
# Prepare for agent termination
|
141
|
+
#
|
142
|
+
# === Return
|
143
|
+
# true:: Always return true
|
144
|
+
def terminate
|
145
|
+
@terminating = true
|
146
|
+
@check_interval = 0
|
147
|
+
if @ping_timer
|
148
|
+
@ping_timer.cancel
|
149
|
+
@ping_timer = nil
|
150
|
+
end
|
151
|
+
if @inactivity_timer
|
152
|
+
@inactivity_timer.cancel
|
153
|
+
@inactivity_timer = nil
|
154
|
+
end
|
155
|
+
true
|
156
|
+
end
|
157
|
+
|
158
|
+
protected
|
159
|
+
|
160
|
+
# Start timer that waits for inactive messaging period to end before checking connectivity
|
161
|
+
#
|
162
|
+
# === Return
|
163
|
+
# true:: Always return true
|
164
|
+
def restart_inactivity_timer
|
165
|
+
@inactivity_timer.cancel if @inactivity_timer
|
166
|
+
@inactivity_timer = EM::Timer.new(@check_interval) do
|
167
|
+
begin
|
168
|
+
check(id = nil, max_ping_timeouts = 1)
|
169
|
+
rescue Exception => e
|
170
|
+
Log.error("Failed connectivity check", e, :trace)
|
171
|
+
@exception_stats.track("check connectivity", e)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
true
|
175
|
+
end
|
176
|
+
|
177
|
+
end # ConnectivityChecker
|
178
|
+
|
179
|
+
end # RightScale
|