right_agent 0.5.1
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 +78 -0
- data/Rakefile +86 -0
- data/lib/right_agent.rb +66 -0
- data/lib/right_agent/actor.rb +163 -0
- data/lib/right_agent/actor_registry.rb +76 -0
- data/lib/right_agent/actors/agent_manager.rb +189 -0
- data/lib/right_agent/agent.rb +735 -0
- data/lib/right_agent/agent_config.rb +403 -0
- data/lib/right_agent/agent_identity.rb +209 -0
- data/lib/right_agent/agent_tags_manager.rb +213 -0
- data/lib/right_agent/audit_formatter.rb +107 -0
- data/lib/right_agent/broker_client.rb +683 -0
- data/lib/right_agent/command.rb +30 -0
- data/lib/right_agent/command/agent_manager_commands.rb +134 -0
- data/lib/right_agent/command/command_client.rb +136 -0
- data/lib/right_agent/command/command_constants.rb +42 -0
- data/lib/right_agent/command/command_io.rb +128 -0
- data/lib/right_agent/command/command_parser.rb +87 -0
- data/lib/right_agent/command/command_runner.rb +105 -0
- data/lib/right_agent/command/command_serializer.rb +63 -0
- data/lib/right_agent/console.rb +65 -0
- data/lib/right_agent/core_payload_types.rb +42 -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 +90 -0
- data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
- data/lib/right_agent/core_payload_types/executable_bundle.rb +138 -0
- data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
- data/lib/right_agent/core_payload_types/login_user.rb +62 -0
- data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
- data/lib/right_agent/core_payload_types/recipe_instantiation.rb +60 -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 +73 -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/dispatcher.rb +348 -0
- data/lib/right_agent/enrollment_result.rb +217 -0
- data/lib/right_agent/exceptions.rb +30 -0
- data/lib/right_agent/ha_broker_client.rb +1278 -0
- data/lib/right_agent/idempotent_request.rb +140 -0
- data/lib/right_agent/log.rb +418 -0
- data/lib/right_agent/monkey_patches.rb +29 -0
- data/lib/right_agent/monkey_patches/amqp_patch.rb +274 -0
- data/lib/right_agent/monkey_patches/ruby_patch.rb +49 -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/singleton_patch.rb +46 -0
- data/lib/right_agent/monkey_patches/ruby_patch/string_patch.rb +107 -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 +90 -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 +91 -0
- data/lib/right_agent/operation_result.rb +270 -0
- data/lib/right_agent/packets.rb +637 -0
- data/lib/right_agent/payload_formatter.rb +104 -0
- data/lib/right_agent/pid_file.rb +159 -0
- data/lib/right_agent/platform.rb +319 -0
- data/lib/right_agent/platform/darwin.rb +227 -0
- data/lib/right_agent/platform/linux.rb +268 -0
- data/lib/right_agent/platform/windows.rb +1204 -0
- data/lib/right_agent/scripts/agent_controller.rb +522 -0
- data/lib/right_agent/scripts/agent_deployer.rb +379 -0
- data/lib/right_agent/scripts/common_parser.rb +153 -0
- data/lib/right_agent/scripts/log_level_manager.rb +193 -0
- data/lib/right_agent/scripts/stats_manager.rb +256 -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 +63 -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 +84 -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 +69 -0
- data/lib/right_agent/sender.rb +937 -0
- data/lib/right_agent/serialize.rb +29 -0
- data/lib/right_agent/serialize/message_pack.rb +102 -0
- data/lib/right_agent/serialize/secure_serializer.rb +131 -0
- data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
- data/lib/right_agent/serialize/serializable.rb +135 -0
- data/lib/right_agent/serialize/serializer.rb +149 -0
- data/lib/right_agent/stats_helper.rb +731 -0
- data/lib/right_agent/subprocess.rb +38 -0
- data/lib/right_agent/tracer.rb +124 -0
- data/right_agent.gemspec +60 -0
- data/spec/actor_registry_spec.rb +81 -0
- data/spec/actor_spec.rb +99 -0
- data/spec/agent_config_spec.rb +226 -0
- data/spec/agent_identity_spec.rb +75 -0
- data/spec/agent_spec.rb +571 -0
- data/spec/broker_client_spec.rb +961 -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 +72 -0
- data/spec/command/command_serializer_spec.rb +51 -0
- data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
- data/spec/core_payload_types/executable_bundle_spec.rb +59 -0
- data/spec/core_payload_types/login_user_spec.rb +98 -0
- data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
- data/spec/core_payload_types/spec_helper.rb +23 -0
- data/spec/dispatcher_spec.rb +372 -0
- data/spec/enrollment_result_spec.rb +53 -0
- data/spec/ha_broker_client_spec.rb +1673 -0
- data/spec/idempotent_request_spec.rb +136 -0
- data/spec/log_spec.rb +177 -0
- data/spec/monkey_patches/amqp_patch_spec.rb +100 -0
- data/spec/monkey_patches/eventmachine_spec.rb +62 -0
- data/spec/monkey_patches/string_patch_spec.rb +99 -0
- data/spec/multiplexer_spec.rb +48 -0
- data/spec/operation_result_spec.rb +171 -0
- data/spec/packets_spec.rb +418 -0
- data/spec/platform/platform_spec.rb +60 -0
- data/spec/results_mock.rb +45 -0
- data/spec/secure_identity_spec.rb +50 -0
- data/spec/security/cached_certificate_store_proxy_spec.rb +56 -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 +52 -0
- data/spec/sender_spec.rb +887 -0
- data/spec/serialize/message_pack_spec.rb +131 -0
- data/spec/serialize/secure_serializer_spec.rb +102 -0
- data/spec/serialize/serializable_spec.rb +90 -0
- data/spec/serialize/serializer_spec.rb +174 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +77 -0
- data/spec/stats_helper_spec.rb +681 -0
- data/spec/tracer_spec.rb +114 -0
- metadata +320 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
# === Synopsis:
|
|
2
|
+
# RightScale RightAgent Controller (rnac) - (c) 2009-2011 RightScale Inc
|
|
3
|
+
#
|
|
4
|
+
# rnac is a command line tool for managing a RightAgent
|
|
5
|
+
#
|
|
6
|
+
# === Examples:
|
|
7
|
+
# Start new agent named AGENT:
|
|
8
|
+
# rnac --start AGENT
|
|
9
|
+
# rnac -s AGENT
|
|
10
|
+
#
|
|
11
|
+
# Stop running agent named AGENT:
|
|
12
|
+
# rnac --stop AGENT
|
|
13
|
+
# rnac -p AGENT
|
|
14
|
+
#
|
|
15
|
+
# Stop agent with given serialized ID:
|
|
16
|
+
# rnac --stop-agent ID
|
|
17
|
+
#
|
|
18
|
+
# Terminate all agents on local machine:
|
|
19
|
+
# rnac --killall
|
|
20
|
+
# rnac -K
|
|
21
|
+
#
|
|
22
|
+
# List agents configured on local machine:
|
|
23
|
+
# rnac --list
|
|
24
|
+
# rnac -l
|
|
25
|
+
#
|
|
26
|
+
# List status of agents configured on local machine:
|
|
27
|
+
# rnac --status
|
|
28
|
+
# rnac -U
|
|
29
|
+
#
|
|
30
|
+
# Start new agent named AGENT in foreground:
|
|
31
|
+
# rnac --start AGENT --foreground
|
|
32
|
+
# rnac -s AGENT -f
|
|
33
|
+
#
|
|
34
|
+
# Start new agent named AGENT of type TYPE:
|
|
35
|
+
# rnac --start AGENT --type TYPE
|
|
36
|
+
# rnac -s AGENT -t TYPE
|
|
37
|
+
#
|
|
38
|
+
# Note: To start multiple agents of the same type generate one
|
|
39
|
+
# config.yml file with rad and then start each agent with rnac:
|
|
40
|
+
# rad my_agent
|
|
41
|
+
# rnac -s my_agent_1 -t my_agent
|
|
42
|
+
# rnac -s my_agent_2 -t my_agent
|
|
43
|
+
#
|
|
44
|
+
# === Usage:
|
|
45
|
+
# rnac [options]
|
|
46
|
+
#
|
|
47
|
+
# options:
|
|
48
|
+
# --start, -s AGENT Start agent named AGENT
|
|
49
|
+
# --stop, -p AGENT Stop agent named AGENT
|
|
50
|
+
# --stop-agent ID Stop agent with serialized identity ID
|
|
51
|
+
# --kill, -k PIDFILE Kill process with given process id file
|
|
52
|
+
# --killall, -K Stop all running agents
|
|
53
|
+
# --status, -U List running agents on local machine
|
|
54
|
+
# --identity, -i ID Use base id ID to build agent's identity
|
|
55
|
+
# --token, -t TOKEN Use token TOKEN to build agent's identity
|
|
56
|
+
# --prefix, -x PREFIX Use prefix PREFIX to build agent's identity
|
|
57
|
+
# --type TYPE Use agent type TYPE to build agent's' identity,98589
|
|
58
|
+
# defaults to AGENT with any trailing '_[0-9]+' removed
|
|
59
|
+
# --list, -l List all configured agents
|
|
60
|
+
# --user, -u USER Set AMQP user
|
|
61
|
+
# --pass, -p PASS Set AMQP password
|
|
62
|
+
# --vhost, -v VHOST Set AMQP vhost
|
|
63
|
+
# --host, -h HOST Set AMQP server hostname
|
|
64
|
+
# --port, -P PORT Set AMQP server port
|
|
65
|
+
# --cfg-dir, -c DIR Set directory containing configuration for all agents
|
|
66
|
+
# --pid-dir, -z DIR Set directory containing agent process id files
|
|
67
|
+
# --log-dir DIR Set log directory
|
|
68
|
+
# --log-level LVL Log level (debug, info, warning, error or fatal)
|
|
69
|
+
# --foreground, -f Run agent in foreground
|
|
70
|
+
# --interactive, -I Spawn an irb console after starting agent
|
|
71
|
+
# --test Use test settings
|
|
72
|
+
# --help Display help
|
|
73
|
+
|
|
74
|
+
require 'rubygems'
|
|
75
|
+
require 'optparse'
|
|
76
|
+
require 'fileutils'
|
|
77
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'usage'))
|
|
78
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'right_agent'))
|
|
79
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'common_parser'))
|
|
80
|
+
|
|
81
|
+
module RightScale
|
|
82
|
+
|
|
83
|
+
class AgentController
|
|
84
|
+
|
|
85
|
+
include CommonParser
|
|
86
|
+
|
|
87
|
+
FORCED_OPTIONS =
|
|
88
|
+
{
|
|
89
|
+
:threadpool_size => 1
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
DEFAULT_OPTIONS =
|
|
93
|
+
{
|
|
94
|
+
:single_threaded => true,
|
|
95
|
+
:log_dir => Platform.filesystem.log_dir,
|
|
96
|
+
:daemonize => true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@@agent = nil
|
|
100
|
+
|
|
101
|
+
# Create and run controller
|
|
102
|
+
#
|
|
103
|
+
# === Return
|
|
104
|
+
# true:: Always return true
|
|
105
|
+
def self.run
|
|
106
|
+
c = AgentController.new
|
|
107
|
+
c.control(c.parse_args)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Parse arguments and execute request
|
|
111
|
+
#
|
|
112
|
+
# === Parameters
|
|
113
|
+
# options(Hash):: Command line options
|
|
114
|
+
#
|
|
115
|
+
# === Return
|
|
116
|
+
# true:: Always return true
|
|
117
|
+
def control(options)
|
|
118
|
+
# Initialize directory settings
|
|
119
|
+
AgentConfig.cfg_dir = options[:cfg_dir]
|
|
120
|
+
AgentConfig.pid_dir = options[:pid_dir]
|
|
121
|
+
|
|
122
|
+
# List agents if requested
|
|
123
|
+
list_configured_agents if options[:list]
|
|
124
|
+
|
|
125
|
+
# Validate arguments
|
|
126
|
+
action = options.delete(:action)
|
|
127
|
+
fail("No action specified on the command line.", print_usage = true) unless action
|
|
128
|
+
if action == 'kill' && (options[:pid_file].nil? || !File.file?(options[:pid_file]))
|
|
129
|
+
fail("Missing or invalid pid file #{options[:pid_file]}", print_usage = true)
|
|
130
|
+
end
|
|
131
|
+
if options[:agent_name]
|
|
132
|
+
if action == 'start'
|
|
133
|
+
cfg = configure_agent(action, options)
|
|
134
|
+
else
|
|
135
|
+
cfg = AgentConfig.load_cfg(options[:agent_name])
|
|
136
|
+
fail("Deployment is missing configuration file #{AgentConfig.cfg_file(options[:agent_name]).inspect}.") unless cfg
|
|
137
|
+
end
|
|
138
|
+
options.delete(:identity)
|
|
139
|
+
options = cfg.merge(options)
|
|
140
|
+
AgentConfig.root_dir = options[:root_dir]
|
|
141
|
+
AgentConfig.pid_dir = options[:pid_dir]
|
|
142
|
+
Log.program_name = syslog_program_name(options)
|
|
143
|
+
Log.log_to_file_only(options[:log_to_file_only])
|
|
144
|
+
configure_proxy(options[:http_proxy], options[:http_no_proxy]) if options[:http_proxy]
|
|
145
|
+
elsif options[:identity]
|
|
146
|
+
options[:agent_name] = AgentConfig.agent_name(options[:identity])
|
|
147
|
+
end
|
|
148
|
+
@options = DEFAULT_OPTIONS.clone.merge(options.merge(FORCED_OPTIONS))
|
|
149
|
+
FileUtils.mkdir_p(@options[:pid_dir]) unless @options[:pid_dir].nil? || File.directory?(@options[:pid_dir])
|
|
150
|
+
|
|
151
|
+
# Execute request
|
|
152
|
+
success = case action
|
|
153
|
+
when /show|killall/
|
|
154
|
+
action = 'stop' if action == 'killall'
|
|
155
|
+
s = true
|
|
156
|
+
AgentConfig.cfg_agents.each { |agent_name| s &&= dispatch(action, agent_name) }
|
|
157
|
+
s
|
|
158
|
+
when 'kill'
|
|
159
|
+
kill_process
|
|
160
|
+
else
|
|
161
|
+
dispatch(action, @options[:agent_name])
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
exit(1) unless success
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Create options hash from command line arguments
|
|
168
|
+
#
|
|
169
|
+
# === Return
|
|
170
|
+
# options(Hash):: Parsed options
|
|
171
|
+
def parse_args
|
|
172
|
+
options = {}
|
|
173
|
+
|
|
174
|
+
opts = OptionParser.new do |opts|
|
|
175
|
+
parse_common(opts, options)
|
|
176
|
+
parse_other_args(opts, options)
|
|
177
|
+
|
|
178
|
+
opts.on("-s", "--start AGENT") do |a|
|
|
179
|
+
options[:action] = 'start'
|
|
180
|
+
options[:agent_name] = a
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
opts.on("-p", "--stop AGENT") do |a|
|
|
184
|
+
options[:action] = 'stop'
|
|
185
|
+
options[:agent_name] = a
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
opts.on("--stop-agent ID") do |id|
|
|
189
|
+
options[:action] = 'stop'
|
|
190
|
+
options[:identity] = id
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
opts.on("-k", "--kill PIDFILE") do |file|
|
|
194
|
+
options[:pid_file] = file
|
|
195
|
+
options[:action] = 'kill'
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
opts.on("-K", "--killall") do
|
|
199
|
+
options[:action] = 'killall'
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
opts.on("-U", "--status") do
|
|
203
|
+
options[:action] = 'show'
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
opts.on("-l", "--list") do
|
|
207
|
+
options[:list] = true
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
opts.on("--log-level LVL") do |lvl|
|
|
211
|
+
options[:log_level] = lvl
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
opts.on("-c", "--cfg-dir DIR") do |d|
|
|
215
|
+
options[:cfg_dir] = d
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
opts.on("-z", "--pid-dir DIR") do |dir|
|
|
219
|
+
options[:pid_dir] = dir
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
opts.on("--log-dir DIR") do |dir|
|
|
223
|
+
options[:log_dir] = dir
|
|
224
|
+
|
|
225
|
+
# Ensure log directory exists (for windows, etc.)
|
|
226
|
+
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
opts.on("-f", "--foreground") do
|
|
230
|
+
options[:daemonize] = false
|
|
231
|
+
#Squelch Ruby VM warnings about various things
|
|
232
|
+
$VERBOSE = nil
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
opts.on("-I", "--interactive") do
|
|
236
|
+
options[:console] = true
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
opts.on_tail("--help") do
|
|
240
|
+
puts Usage.scan(__FILE__)
|
|
241
|
+
exit
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
begin
|
|
247
|
+
opts.parse(ARGV)
|
|
248
|
+
rescue Exception => e
|
|
249
|
+
exit 0 if e.is_a?(SystemExit)
|
|
250
|
+
fail(e.message, print_usage = true)
|
|
251
|
+
end
|
|
252
|
+
resolve_identity(options)
|
|
253
|
+
options
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
protected
|
|
257
|
+
|
|
258
|
+
# Parse any other arguments used by agent
|
|
259
|
+
#
|
|
260
|
+
# === Parameters
|
|
261
|
+
# opts(OptionParser):: Options parser with options to be parsed
|
|
262
|
+
# options(Hash):: Storage for options that are parsed
|
|
263
|
+
#
|
|
264
|
+
# === Return
|
|
265
|
+
# true:: Always return true
|
|
266
|
+
def parse_other_args(opts, options)
|
|
267
|
+
true
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Dispatch action
|
|
271
|
+
#
|
|
272
|
+
# === Parameters
|
|
273
|
+
# action(String):: Action to be performed
|
|
274
|
+
# agent_name(String):: Agent name
|
|
275
|
+
#
|
|
276
|
+
# === Return
|
|
277
|
+
# true:: Always return true
|
|
278
|
+
def dispatch(action, agent_name)
|
|
279
|
+
# Setup the environment from config if necessary
|
|
280
|
+
begin
|
|
281
|
+
eval("#{action}_agent(agent_name)")
|
|
282
|
+
rescue SystemExit
|
|
283
|
+
true
|
|
284
|
+
rescue SignalException
|
|
285
|
+
true
|
|
286
|
+
rescue Exception => e
|
|
287
|
+
puts Log.format("Failed to #{action} #{agent_name}", e, :trace)
|
|
288
|
+
end
|
|
289
|
+
true
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Kill process defined in pid file
|
|
293
|
+
#
|
|
294
|
+
# === Parameters
|
|
295
|
+
# sig(String):: Signal to be used for kill
|
|
296
|
+
#
|
|
297
|
+
# === Return
|
|
298
|
+
# true:: Always return true
|
|
299
|
+
def kill_process(sig = 'TERM')
|
|
300
|
+
content = IO.read(@options[:pid_file])
|
|
301
|
+
pid = content.to_i
|
|
302
|
+
fail("Invalid pid file content #{content.inspect}") if pid == 0
|
|
303
|
+
begin
|
|
304
|
+
Process.kill(sig, pid)
|
|
305
|
+
rescue Errno::ESRCH => e
|
|
306
|
+
fail("Could not find process with pid #{pid}")
|
|
307
|
+
rescue Errno::EPERM => e
|
|
308
|
+
fail("You don't have permissions to stop process #{pid}")
|
|
309
|
+
rescue Exception => e
|
|
310
|
+
fail(e.message)
|
|
311
|
+
end
|
|
312
|
+
true
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Start agent
|
|
316
|
+
#
|
|
317
|
+
# === Parameters
|
|
318
|
+
# agent_name(String):: Agent name
|
|
319
|
+
# agent_class(Agent):: Agent class
|
|
320
|
+
#
|
|
321
|
+
# === Return
|
|
322
|
+
# true:: Always return true
|
|
323
|
+
def start_agent(agent_name, agent_class = Agent)
|
|
324
|
+
puts "#{human_readable_name} being started"
|
|
325
|
+
|
|
326
|
+
EM.error_handler do |e|
|
|
327
|
+
Log.error("EM block execution failed with exception", e, :trace)
|
|
328
|
+
Log.error("\n\n===== Exiting due to EM block exception =====\n\n")
|
|
329
|
+
EM.stop
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
EM.run do
|
|
333
|
+
begin
|
|
334
|
+
@@agent = agent_class.start(@options)
|
|
335
|
+
rescue SystemExit
|
|
336
|
+
raise # Let parents of forked (daemonized) processes die
|
|
337
|
+
rescue PidFile::AlreadyRunning
|
|
338
|
+
puts "#{human_readable_name} already running"
|
|
339
|
+
EM.stop
|
|
340
|
+
rescue Exception => e
|
|
341
|
+
puts Log.format("#{human_readable_name} failed", e, :trace)
|
|
342
|
+
EM.stop
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
true
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
# Stop agent process
|
|
349
|
+
#
|
|
350
|
+
# === Parameters
|
|
351
|
+
# agent_name(String):: Agent name
|
|
352
|
+
#
|
|
353
|
+
# === Return
|
|
354
|
+
# (Boolean):: true if process was stopped, otherwise false
|
|
355
|
+
def stop_agent(agent_name)
|
|
356
|
+
res = false
|
|
357
|
+
if pid_file = AgentConfig.pid_file(agent_name)
|
|
358
|
+
name = human_readable_name(agent_name, pid_file.identity)
|
|
359
|
+
if pid = pid_file.read_pid[:pid]
|
|
360
|
+
begin
|
|
361
|
+
Process.kill('TERM', pid)
|
|
362
|
+
res = true
|
|
363
|
+
puts "#{name} stopped"
|
|
364
|
+
rescue Errno::ESRCH
|
|
365
|
+
puts "#{name} not running"
|
|
366
|
+
end
|
|
367
|
+
elsif File.file?(pid_file.to_s)
|
|
368
|
+
puts "Invalid pid file '#{pid_file.to_s}' content: #{IO.read(pid_file.to_s)}"
|
|
369
|
+
else
|
|
370
|
+
puts "#{name} not running"
|
|
371
|
+
end
|
|
372
|
+
else
|
|
373
|
+
puts "Non-existent pid file for #{agent_name}"
|
|
374
|
+
end
|
|
375
|
+
res
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# Show status of agent
|
|
379
|
+
#
|
|
380
|
+
# === Parameters
|
|
381
|
+
# agent_name(String):: Agent name
|
|
382
|
+
#
|
|
383
|
+
# === Return
|
|
384
|
+
# (Boolean):: true if process is running, otherwise false
|
|
385
|
+
def show_agent(agent_name)
|
|
386
|
+
res = false
|
|
387
|
+
if (pid_file = AgentConfig.pid_file(agent_name)) && (pid = pid_file.read_pid[:pid])
|
|
388
|
+
pgid = Process.getpgid(pid) rescue -1
|
|
389
|
+
name = human_readable_name(agent_name, pid_file.identity)
|
|
390
|
+
if pgid != -1
|
|
391
|
+
psdata = `ps up #{pid}`.split("\n").last.split
|
|
392
|
+
memory = (psdata[5].to_i / 1024)
|
|
393
|
+
puts "#{name} is alive, using #{memory}MB of memory"
|
|
394
|
+
res = true
|
|
395
|
+
else
|
|
396
|
+
puts "#{name} is not running but has a stale pid file at #{pid_file}"
|
|
397
|
+
end
|
|
398
|
+
elsif identity = AgentConfig.agent_options(agent_name)[:identity]
|
|
399
|
+
puts "#{human_readable_name(agent_name, identity)} is not running"
|
|
400
|
+
end
|
|
401
|
+
res
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# Generate human readable name for agent
|
|
405
|
+
#
|
|
406
|
+
# === Return
|
|
407
|
+
# (String):: Human readable name
|
|
408
|
+
def human_readable_name(agent_name = nil, identity = nil)
|
|
409
|
+
agent_name ||= @options[:agent_name]
|
|
410
|
+
"Agent #{agent_name + ' ' if agent_name}with ID #{identity || @options[:identity]}"
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# List all configured agents
|
|
414
|
+
#
|
|
415
|
+
# === Return
|
|
416
|
+
# never
|
|
417
|
+
def list_configured_agents
|
|
418
|
+
agents = AgentConfig.cfg_agents
|
|
419
|
+
if agents.empty?
|
|
420
|
+
puts "Found no configured agents"
|
|
421
|
+
else
|
|
422
|
+
puts "Configured agents:"
|
|
423
|
+
agents.each { |a| puts " - #{a}" }
|
|
424
|
+
end
|
|
425
|
+
exit
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# Determine syslog program name based on options
|
|
429
|
+
#
|
|
430
|
+
# === Parameters
|
|
431
|
+
# options(Hash):: Command line options
|
|
432
|
+
#
|
|
433
|
+
# === Return
|
|
434
|
+
# (String):: Program name
|
|
435
|
+
def syslog_program_name(options)
|
|
436
|
+
'RightAgent'
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
# Determine configuration settings for this agent and persist them if needed
|
|
440
|
+
# Reuse existing agent identity when possible
|
|
441
|
+
#
|
|
442
|
+
# === Parameters
|
|
443
|
+
# action(String):: Requested action
|
|
444
|
+
# options(Hash):: Command line options
|
|
445
|
+
#
|
|
446
|
+
# === Return
|
|
447
|
+
# cfg(Hash):: Persisted configuration options
|
|
448
|
+
def configure_agent(action, options)
|
|
449
|
+
agent_type = options[:agent_type]
|
|
450
|
+
agent_name = options[:agent_name]
|
|
451
|
+
if agent_name != agent_type && cfg = AgentConfig.load_cfg(agent_type)
|
|
452
|
+
base_id = (options[:base_id] || AgentIdentity.parse(cfg[:identity]).base_id.to_s).to_i
|
|
453
|
+
unless (identity = AgentConfig.agent_options(agent_name)[:identity]) &&
|
|
454
|
+
AgentIdentity.parse(identity).base_id == base_id
|
|
455
|
+
identity = AgentIdentity.new(options[:prefix] || 'rs', options[:agent_type], base_id, options[:token]).to_s
|
|
456
|
+
end
|
|
457
|
+
cfg.merge!(:identity => identity)
|
|
458
|
+
cfg_file = AgentConfig.store_cfg(agent_name, cfg)
|
|
459
|
+
puts "Generated configuration file for #{agent_name} agent: #{cfg_file}"
|
|
460
|
+
elsif !(cfg = AgentConfig.load_cfg(agent_name))
|
|
461
|
+
fail("Deployment is missing configuration file #{AgentConfig.cfg_file(agent_name).inspect}")
|
|
462
|
+
end
|
|
463
|
+
cfg
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# Enable the use of an HTTP proxy for this process and its subprocesses
|
|
467
|
+
#
|
|
468
|
+
# === Parameters
|
|
469
|
+
# proxy_setting(String):: Proxy to use
|
|
470
|
+
# exceptions(String):: Comma-separated list of proxy exceptions (e.g. metadata server)
|
|
471
|
+
#
|
|
472
|
+
# === Return
|
|
473
|
+
# true:: Always return true
|
|
474
|
+
def configure_proxy(proxy_setting, exceptions)
|
|
475
|
+
ENV['HTTP_PROXY'] = proxy_setting
|
|
476
|
+
ENV['http_proxy'] = proxy_setting
|
|
477
|
+
ENV['HTTPS_PROXY'] = proxy_setting
|
|
478
|
+
ENV['https_proxy'] = proxy_setting
|
|
479
|
+
ENV['NO_PROXY'] = exceptions
|
|
480
|
+
ENV['no_proxy'] = exceptions
|
|
481
|
+
true
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
# Print error on console and exit abnormally
|
|
485
|
+
#
|
|
486
|
+
# === Parameters
|
|
487
|
+
# message(String):: Error message to be displayed
|
|
488
|
+
# print_usage(Boolean):: Whether to display usage information
|
|
489
|
+
#
|
|
490
|
+
# === Return
|
|
491
|
+
# never
|
|
492
|
+
def fail(message, print_usage = false)
|
|
493
|
+
puts "** #{message}"
|
|
494
|
+
puts Usage.scan(__FILE__) if print_usage
|
|
495
|
+
exit(1)
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
end # AgentController
|
|
499
|
+
|
|
500
|
+
end # RightScale
|
|
501
|
+
|
|
502
|
+
#
|
|
503
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
|
504
|
+
#
|
|
505
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
506
|
+
# a copy of this software and associated documentation files (the
|
|
507
|
+
# "Software"), to deal in the Software without restriction, including
|
|
508
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
509
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
510
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
511
|
+
# the following conditions:
|
|
512
|
+
#
|
|
513
|
+
# The above copyright notice and this permission notice shall be
|
|
514
|
+
# included in all copies or substantial portions of the Software.
|
|
515
|
+
#
|
|
516
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
517
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
518
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
519
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
520
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
521
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
522
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|