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,30 @@
|
|
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
|
+
COMMAND_BASE_DIR = File.join(File.dirname(__FILE__), 'command')
|
24
|
+
|
25
|
+
require File.normalize_path(File.join(COMMAND_BASE_DIR, 'command_constants'))
|
26
|
+
require File.normalize_path(File.join(COMMAND_BASE_DIR, 'command_parser'))
|
27
|
+
require File.normalize_path(File.join(COMMAND_BASE_DIR, 'command_serializer'))
|
28
|
+
require File.normalize_path(File.join(COMMAND_BASE_DIR, 'command_io'))
|
29
|
+
require File.normalize_path(File.join(COMMAND_BASE_DIR, 'command_runner'))
|
30
|
+
require File.normalize_path(File.join(COMMAND_BASE_DIR, 'command_client'))
|
@@ -0,0 +1,150 @@
|
|
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
|
+
# Commands exposed by agent that has an AgentManager actor
|
26
|
+
class AgentManagerCommands
|
27
|
+
|
28
|
+
# List of command names associated with description
|
29
|
+
# The commands should be implemented in methods in this class named '<name>_command'
|
30
|
+
# where <name> is the name of the command.
|
31
|
+
COMMANDS = {
|
32
|
+
:list => 'List all available commands with their description',
|
33
|
+
:set_log_level => 'Set log level to options[:level]',
|
34
|
+
:get_log_level => 'Get log level',
|
35
|
+
:ping => 'Ping agent',
|
36
|
+
:stats => 'Get statistics about agent operation',
|
37
|
+
:profile => 'Manage memory profiling',
|
38
|
+
:terminate => 'Terminate agent'
|
39
|
+
}
|
40
|
+
|
41
|
+
# Build hash of commands associating command names with block
|
42
|
+
#
|
43
|
+
# === Parameter
|
44
|
+
# agent_manager(AgentManager):: Agent manager used by ping and stats commands
|
45
|
+
#
|
46
|
+
# === Return
|
47
|
+
# cmds(Hash):: Hash of command blocks keyed by command names
|
48
|
+
def self.get(agent_manager)
|
49
|
+
cmds = {}
|
50
|
+
target = new(agent_manager)
|
51
|
+
COMMANDS.each { |k, v| cmds[k] = lambda { |opts, conn| opts[:conn] = conn; target.send("#{k.to_s}_command", opts) } }
|
52
|
+
cmds
|
53
|
+
end
|
54
|
+
|
55
|
+
# Initialize command server
|
56
|
+
#
|
57
|
+
# === Parameter
|
58
|
+
# agent_manager(AgentManager):: Agent manager used by ping and stats commands
|
59
|
+
def initialize(agent_manager)
|
60
|
+
@agent_manager = agent_manager
|
61
|
+
@serializer = Serializer.new
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
# List command implementation
|
67
|
+
#
|
68
|
+
# === Parameters
|
69
|
+
# opts(Hash):: Should contain the connection for sending data
|
70
|
+
#
|
71
|
+
# === Return
|
72
|
+
# true:: Always return true
|
73
|
+
def list_command(opts)
|
74
|
+
usage = "Agent exposes the following commands:\n"
|
75
|
+
COMMANDS.reject { |k, _| k == :list || k.to_s =~ /test/ }.each do |c|
|
76
|
+
c.each { |k, v| usage += " - #{k.to_s}: #{v}\n" }
|
77
|
+
end
|
78
|
+
CommandIO.instance.reply(opts[:conn], usage)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Set log level command
|
82
|
+
#
|
83
|
+
# === Return
|
84
|
+
# true:: Always return true
|
85
|
+
def set_log_level_command(opts)
|
86
|
+
Log.level = opts[:level] if [ :debug, :info, :warn, :error, :fatal ].include?(opts[:level])
|
87
|
+
CommandIO.instance.reply(opts[:conn], Log.level)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get log level command
|
91
|
+
#
|
92
|
+
# === Return
|
93
|
+
# true:: Always return true
|
94
|
+
def get_log_level_command(opts)
|
95
|
+
CommandIO.instance.reply(opts[:conn], Log.level)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Ping command
|
99
|
+
#
|
100
|
+
# === Parameters
|
101
|
+
# opts[:conn](EM::Connection):: Connection used to send reply
|
102
|
+
#
|
103
|
+
# === Return
|
104
|
+
# true
|
105
|
+
def ping_command(opts)
|
106
|
+
CommandIO.instance.reply(opts[:conn], @serializer.dump(@agent_manager.ping))
|
107
|
+
end
|
108
|
+
|
109
|
+
# Stats command
|
110
|
+
#
|
111
|
+
# === Parameters
|
112
|
+
# opts[:conn](EM::Connection):: Connection used to send reply
|
113
|
+
# opts[:reset](Boolean):: Whether to reset stats
|
114
|
+
#
|
115
|
+
# === Return
|
116
|
+
# true
|
117
|
+
def stats_command(opts)
|
118
|
+
CommandIO.instance.reply(opts[:conn], @serializer.dump(@agent_manager.stats({:reset => opts[:reset]})))
|
119
|
+
end
|
120
|
+
|
121
|
+
# Profile command
|
122
|
+
#
|
123
|
+
# === Parameters
|
124
|
+
# opts[:conn](EM::Connection):: Connection used to send reply
|
125
|
+
# opts[:start](Boolean):: Whether to start profiling
|
126
|
+
# opts[:stats](Boolean):: Whether to display profile statistics to stdout
|
127
|
+
# opts[:reset](Boolean):: Whether to reset profile statistics when after displaying them
|
128
|
+
# opts[:stop](Boolean):: Whether to stop profiling
|
129
|
+
#
|
130
|
+
# === Return
|
131
|
+
# true
|
132
|
+
def profile_command(opts)
|
133
|
+
CommandIO.instance.reply(opts[:conn], @serializer.dump(@agent_manager.profile(opts)))
|
134
|
+
end
|
135
|
+
|
136
|
+
# Terminate command
|
137
|
+
#
|
138
|
+
# === Parameters
|
139
|
+
# opts[:conn](EM::Connection):: Connection used to send reply
|
140
|
+
#
|
141
|
+
# === Return
|
142
|
+
# true:: Always return true
|
143
|
+
def terminate_command(opts)
|
144
|
+
CommandIO.instance.reply(opts[:conn], 'Terminating')
|
145
|
+
@agent_manager.terminate
|
146
|
+
end
|
147
|
+
|
148
|
+
end # AgentManagerCommands
|
149
|
+
|
150
|
+
end # RightScale
|
@@ -0,0 +1,136 @@
|
|
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
|
+
class CommandClient
|
26
|
+
|
27
|
+
# Agent response if any
|
28
|
+
attr_accessor :response
|
29
|
+
|
30
|
+
# Create client
|
31
|
+
#
|
32
|
+
# === Parameters
|
33
|
+
# socket_port(Integer):: Socket port on which to connect to agent
|
34
|
+
# cookie(String):: Cookie associated with command server
|
35
|
+
def initialize(socket_port, cookie)
|
36
|
+
@socket_port = socket_port
|
37
|
+
@cookie = cookie
|
38
|
+
@pending = 0
|
39
|
+
end
|
40
|
+
|
41
|
+
# Stop command client
|
42
|
+
#
|
43
|
+
# === Block
|
44
|
+
# Given block gets called back once last response has been received or timeout
|
45
|
+
def stop(&close_handler)
|
46
|
+
if @pending > 0
|
47
|
+
@close_timeout = EM::Timer.new(@last_timeout) { close_handler.call(timeout=true) }
|
48
|
+
@close_handler = lambda { @close_timeout.cancel; close_handler.call(timeout=false) }
|
49
|
+
else
|
50
|
+
close_handler.call(timeout=false)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Send command to running agent
|
55
|
+
#
|
56
|
+
# === Parameters
|
57
|
+
# options(Hash):: Hash of options and command name
|
58
|
+
# options[:name]:: Command name
|
59
|
+
# options[:...]:: Other command specific options, passed through to agent
|
60
|
+
# verbose(Boolean):: Whether client should display debug info
|
61
|
+
# timeout(Integer):: Number of seconds we should wait for a reply from the agent
|
62
|
+
#
|
63
|
+
# === Block
|
64
|
+
# handler: Command results handler
|
65
|
+
#
|
66
|
+
# === Return
|
67
|
+
# true:: Always return true
|
68
|
+
#
|
69
|
+
# === Raise
|
70
|
+
# RuntimeError:: Timed out waiting for result, raised in EM thread
|
71
|
+
def send_command(options, verbose=false, timeout=20, &handler)
|
72
|
+
return if @closing
|
73
|
+
@last_timeout = timeout
|
74
|
+
manage_em = !EM.reactor_running?
|
75
|
+
response_handler = lambda do
|
76
|
+
EM.stop if manage_em
|
77
|
+
handler.call(@response) if handler && @response
|
78
|
+
@pending -= 1
|
79
|
+
@close_handler.call if @close_handler && @pending == 0
|
80
|
+
end
|
81
|
+
send_handler = lambda do
|
82
|
+
@pending += 1
|
83
|
+
command = options.dup
|
84
|
+
command[:verbose] = verbose
|
85
|
+
command[:cookie] = @cookie
|
86
|
+
EM.next_tick { EM.connect('127.0.0.1', @socket_port, ConnectionHandler, command, self, response_handler) }
|
87
|
+
EM.add_timer(timeout) { EM.stop; raise 'Timed out waiting for agent reply' } if manage_em
|
88
|
+
end
|
89
|
+
if manage_em
|
90
|
+
EM.run { send_handler.call }
|
91
|
+
else
|
92
|
+
send_handler.call
|
93
|
+
end
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
# EventMachine connection handler which sends command to agent
|
100
|
+
# and waits for response
|
101
|
+
module ConnectionHandler
|
102
|
+
|
103
|
+
# Initialize command
|
104
|
+
#
|
105
|
+
# === Parameters
|
106
|
+
# command(Hash):: Command to be sent
|
107
|
+
# client(RightScale::CommandClient):: Client whose response field should be initialized
|
108
|
+
# callback(Proc):: Called back after response has been set
|
109
|
+
def initialize(command, client, callback)
|
110
|
+
@command = command
|
111
|
+
@parser = CommandParser.new do |data|
|
112
|
+
close_connection
|
113
|
+
client.response = data
|
114
|
+
callback.call
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Send command to agent
|
119
|
+
# Called by EventMachine after connection with agent has been established
|
120
|
+
#
|
121
|
+
# === Return
|
122
|
+
# true:: Always return true
|
123
|
+
def post_init
|
124
|
+
puts "Sending command #{@command.inspect}" if @command[:verbose]
|
125
|
+
send_data(CommandSerializer.dump(@command))
|
126
|
+
true
|
127
|
+
end
|
128
|
+
|
129
|
+
# Handle agent response
|
130
|
+
def receive_data(data)
|
131
|
+
@parser.parse_chunk(data)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,33 @@
|
|
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 CommandConstants
|
27
|
+
|
28
|
+
# Ports used for command protocol
|
29
|
+
BASE_INSTANCE_AGENT_SOCKET_PORT = 53843
|
30
|
+
BASE_INSTANCE_AGENT_CHECKER_SOCKET_PORT = 53844
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# Copyright (c) 2009-2011 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and
|
10
|
+
# the licensee.
|
11
|
+
|
12
|
+
module RightScale
|
13
|
+
|
14
|
+
# Class which allows listening for data and sending data on sockets
|
15
|
+
# This allows other processes running on the same machine to send commands to
|
16
|
+
# the agent without having to go through RabbitMQ.
|
17
|
+
class CommandIO
|
18
|
+
|
19
|
+
include RightSupport::Ruby::EasySingleton
|
20
|
+
|
21
|
+
# ensure uniqueness of handler to avoid confusion.
|
22
|
+
raise "#{ServerInputHandler.name} is already defined" if defined?(ServerInputHandler)
|
23
|
+
|
24
|
+
# EventMachine connection
|
25
|
+
# Define event loop callbacks handler
|
26
|
+
module ServerInputHandler
|
27
|
+
|
28
|
+
# Keep block used to handle incoming data
|
29
|
+
#
|
30
|
+
# === Parameters
|
31
|
+
# handler(Proc):: Incoming data handler should take two arguments:
|
32
|
+
# * First argument contains command
|
33
|
+
# * Second argument contains connection used to reply
|
34
|
+
def initialize(handler)
|
35
|
+
@handler = handler
|
36
|
+
@parser = CommandParser.new { |cmd| handler.call(cmd, self) }
|
37
|
+
end
|
38
|
+
|
39
|
+
# EventMachine loop callback called whenever there is data coming from the socket
|
40
|
+
#
|
41
|
+
# === Parameter
|
42
|
+
# data(String):: Incoming data
|
43
|
+
#
|
44
|
+
# === Return
|
45
|
+
# true:: Always return true
|
46
|
+
def receive_data(data)
|
47
|
+
@parser.parse_chunk(data)
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
# Is listener currently waiting for input?
|
54
|
+
#
|
55
|
+
# === Return
|
56
|
+
# true:: If 'listen' was last called
|
57
|
+
# false:: Otherwise
|
58
|
+
def listening
|
59
|
+
!@conn.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
# Open command socket and wait for input on it
|
63
|
+
# This can only be called again after 'stop_listening' was called
|
64
|
+
#
|
65
|
+
# === Parameters
|
66
|
+
# socket_port(Integer):: Socket port on which to listen
|
67
|
+
#
|
68
|
+
# === Block
|
69
|
+
# The given block should take two arguments:
|
70
|
+
# * First argument will be given the commands sent through the socket
|
71
|
+
# Commands should be serialized using RightScale::CommandSerializer.
|
72
|
+
# * Second argument contains the connection that should be given back to
|
73
|
+
# +reply+ to send reply
|
74
|
+
#
|
75
|
+
# === Return
|
76
|
+
# true:: Always return true
|
77
|
+
#
|
78
|
+
# === Raise
|
79
|
+
# (ArgumentError):: If block is missing
|
80
|
+
# (Exceptions::Application):: If +listen+ has already been called and +stop+ hasn't since
|
81
|
+
# (Exceptions::Application):: If port is already bound
|
82
|
+
def listen(socket_port, &block)
|
83
|
+
raise ArgumentError, 'Missing listener block' unless block_given?
|
84
|
+
raise Exceptions::Application, 'Already listening' if listening
|
85
|
+
begin
|
86
|
+
@conn = EM.start_server('127.0.0.1', socket_port, ServerInputHandler, block)
|
87
|
+
rescue Exception => e
|
88
|
+
raise Exceptions::IO, 'Listen port unavailable' if e.message =~ /no acceptor/
|
89
|
+
end
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
# Stop listening for commands
|
94
|
+
# Do nothing if already stopped
|
95
|
+
#
|
96
|
+
# === Return
|
97
|
+
# true:: If command listener was listening
|
98
|
+
# false:: Otherwise
|
99
|
+
def stop_listening
|
100
|
+
res = !@conn.nil?
|
101
|
+
if res
|
102
|
+
EM.stop_server(@conn)
|
103
|
+
@conn = nil
|
104
|
+
end
|
105
|
+
res
|
106
|
+
end
|
107
|
+
|
108
|
+
# Write given data to socket, must be listening
|
109
|
+
#
|
110
|
+
# === Parameters
|
111
|
+
# conn(EM::Connection):: Connection used to send data
|
112
|
+
# data(String):: Data that should be written
|
113
|
+
# close_after_writing(TrueClass|FalseClass):: Whether TCP connection with client should be
|
114
|
+
# closed after reply is sent
|
115
|
+
#
|
116
|
+
# === Return
|
117
|
+
# true:: Always return true
|
118
|
+
def reply(conn, data, close_after_writing=true)
|
119
|
+
conn.send_data(CommandSerializer.dump(data))
|
120
|
+
conn.close_connection_after_writing if close_after_writing
|
121
|
+
true
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|