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,300 @@
|
|
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
|
+
# Container for status and result of an operation
|
27
|
+
class OperationResult
|
28
|
+
|
29
|
+
include Serializable
|
30
|
+
|
31
|
+
# Result status code
|
32
|
+
SUCCESS = 0
|
33
|
+
ERROR = 1
|
34
|
+
CONTINUE = 2
|
35
|
+
RETRY = 3
|
36
|
+
NON_DELIVERY = 4
|
37
|
+
MULTICAST = 5 # Deprecated for agents at version 13 or above
|
38
|
+
CANCEL = 6
|
39
|
+
|
40
|
+
# Non-delivery reasons
|
41
|
+
NON_DELIVERY_REASONS = [
|
42
|
+
NO_TARGET = "no target",
|
43
|
+
UNKNOWN_TARGET = "unknown target",
|
44
|
+
NO_ROUTE_TO_TARGET = "no route to target",
|
45
|
+
TARGET_NOT_CONNECTED = "target not connected",
|
46
|
+
TTL_EXPIRATION = "TTL expiration",
|
47
|
+
RETRY_TIMEOUT = "retry timeout"
|
48
|
+
]
|
49
|
+
|
50
|
+
# Maximum characters included in display of error
|
51
|
+
MAX_ERROR_SIZE = 60
|
52
|
+
|
53
|
+
# (Integer) Status code
|
54
|
+
attr_accessor :status_code
|
55
|
+
|
56
|
+
# (Object) Result data, if any
|
57
|
+
attr_accessor :content
|
58
|
+
|
59
|
+
def initialize(*args)
|
60
|
+
@status_code = args[0]
|
61
|
+
@content = args[1] if args.size > 1
|
62
|
+
end
|
63
|
+
|
64
|
+
# User friendly result
|
65
|
+
# Does not include content except in the case of error or non-delivery
|
66
|
+
#
|
67
|
+
# === Return
|
68
|
+
# (String):: Name of result code
|
69
|
+
def to_s
|
70
|
+
status(reason = true)
|
71
|
+
end
|
72
|
+
|
73
|
+
# User friendly result status
|
74
|
+
#
|
75
|
+
# === Parameters
|
76
|
+
# reason(Boolean):: Whether to include failure reason information, default to false
|
77
|
+
#
|
78
|
+
# === Return
|
79
|
+
# (String):: Name of result code
|
80
|
+
def status(reason = false)
|
81
|
+
case @status_code
|
82
|
+
when SUCCESS then 'success'
|
83
|
+
when ERROR then 'error' + (reason ? " (#{truncated_error})" : "")
|
84
|
+
when CONTINUE then 'continue'
|
85
|
+
when RETRY then 'retry' + (reason ? " (#{@content})" : "")
|
86
|
+
when NON_DELIVERY then 'non-delivery' + (reason ? " (#{@content})" : "")
|
87
|
+
when MULTICAST then 'multicast'
|
88
|
+
when CANCEL then 'cancel' + (reason ? " (#{@content})" : "")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Limited length error string
|
93
|
+
#
|
94
|
+
# === Return
|
95
|
+
# e(String):: String of no more than MAX_ERROR_SIZE characters
|
96
|
+
def truncated_error
|
97
|
+
e = @content.is_a?(String) ? @content : @content.inspect
|
98
|
+
e = e[0, MAX_ERROR_SIZE - 3] + "..." if e.size > (MAX_ERROR_SIZE - 3)
|
99
|
+
e
|
100
|
+
end
|
101
|
+
|
102
|
+
# Instantiate from request result
|
103
|
+
# Ignore all but first result if result is a hash
|
104
|
+
#
|
105
|
+
# === Parameters
|
106
|
+
# result(Result|Hash|OperationResult|nil):: Result or the Result "results" field
|
107
|
+
#
|
108
|
+
# === Return
|
109
|
+
# (RightScale::OperationResult):: Converted operation result
|
110
|
+
def self.from_results(result)
|
111
|
+
r = result.is_a?(Result) ? result.results : result
|
112
|
+
if r && r.respond_to?(:status_code) && r.respond_to?(:content)
|
113
|
+
new(r.status_code, r.content)
|
114
|
+
elsif r && r.is_a?(Hash) && r.values.size > 0
|
115
|
+
r = r.values[0]
|
116
|
+
if r.respond_to?(:status_code) && r.respond_to?(:content)
|
117
|
+
new(r.status_code, r.content)
|
118
|
+
else
|
119
|
+
error("Invalid operation result content: #{r.inspect}")
|
120
|
+
end
|
121
|
+
elsif r && r.is_a?(String)
|
122
|
+
# This is not a supported return value but older RightLink versions can incorrectly
|
123
|
+
# return a String rather than an OperationResult#error in situations where the actor
|
124
|
+
# raises an exception when processing a request
|
125
|
+
error(r)
|
126
|
+
elsif r.nil?
|
127
|
+
error("No results")
|
128
|
+
elsif result.is_a?(Result)
|
129
|
+
error("Invalid results in Result from #{result.from}: #{result.results.inspect}")
|
130
|
+
else
|
131
|
+
error("Invalid operation result type: #{result.inspect}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Create new success status
|
136
|
+
#
|
137
|
+
# === Parameters
|
138
|
+
# content(Object):: Any data associated with successful results, defaults to nil
|
139
|
+
#
|
140
|
+
# === Return
|
141
|
+
# (OperationResult):: Corresponding result
|
142
|
+
def self.success(content = nil)
|
143
|
+
OperationResult.new(SUCCESS, content)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Create new error status
|
147
|
+
#
|
148
|
+
# === Parameters
|
149
|
+
# message(String):: Error description
|
150
|
+
# exception(Exception|String):: Associated exception or other parenthetical error information
|
151
|
+
# backtrace(Symbol):: Exception backtrace extent: :no_trace, :caller, or :trace,
|
152
|
+
# defaults to :caller
|
153
|
+
#
|
154
|
+
# === Return
|
155
|
+
# (OperationResult):: Corresponding result
|
156
|
+
def self.error(message, exception = nil, backtrace = :caller)
|
157
|
+
OperationResult.new(ERROR, Log.format(message, exception, backtrace))
|
158
|
+
end
|
159
|
+
|
160
|
+
# Create new continue status
|
161
|
+
#
|
162
|
+
# === Parameters
|
163
|
+
# content(Object):: Any data associated with continue, defaults to nil
|
164
|
+
#
|
165
|
+
# === Return
|
166
|
+
# (OperationResult):: Corresponding result
|
167
|
+
def self.continue(content = nil)
|
168
|
+
OperationResult.new(CONTINUE, content)
|
169
|
+
end
|
170
|
+
|
171
|
+
# Create new retry status
|
172
|
+
#
|
173
|
+
# === Parameters
|
174
|
+
# content(Object):: Any data associated with retry, defaults to nil
|
175
|
+
#
|
176
|
+
# === Return
|
177
|
+
# (OperationResult):: Corresponding result
|
178
|
+
def self.retry(content = nil)
|
179
|
+
OperationResult.new(RETRY, content)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Create new non-delivery status
|
183
|
+
#
|
184
|
+
# === Parameters
|
185
|
+
# reason(String):: Non-delivery reason from NON_DELIVERY_REASONS
|
186
|
+
#
|
187
|
+
# === Return
|
188
|
+
# (OperationResult):: Corresponding result
|
189
|
+
def self.non_delivery(reason)
|
190
|
+
OperationResult.new(NON_DELIVERY, reason)
|
191
|
+
end
|
192
|
+
|
193
|
+
# Create new multicast status
|
194
|
+
# Deprecated for agents at version 13 or above
|
195
|
+
#
|
196
|
+
# === Parameters
|
197
|
+
# targets(Array):: Identity of targets to which request was published
|
198
|
+
#
|
199
|
+
# === Return
|
200
|
+
# (OperationResult):: Corresponding result
|
201
|
+
def self.multicast(targets)
|
202
|
+
OperationResult.new(MULTICAST, targets)
|
203
|
+
end
|
204
|
+
|
205
|
+
# Cancel request and never retry
|
206
|
+
#
|
207
|
+
# === Parameters
|
208
|
+
# content(Object):: Any data associated with cancel, defaults to nil
|
209
|
+
#
|
210
|
+
# === Return
|
211
|
+
# (OperationResult):: Corresponding result
|
212
|
+
def self.cancel(content = nil)
|
213
|
+
OperationResult.new(CANCEL, content)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Was last operation successful?
|
217
|
+
#
|
218
|
+
# === Return
|
219
|
+
# true:: If status is SUCCESS or CONTINUE
|
220
|
+
# false:: Otherwise
|
221
|
+
def success?
|
222
|
+
status_code == SUCCESS || status_code == CONTINUE
|
223
|
+
end
|
224
|
+
|
225
|
+
# Was last operation unsuccessful?
|
226
|
+
#
|
227
|
+
# === Return
|
228
|
+
# true:: If status is ERROR or NON_DELIVERY
|
229
|
+
# false:: Otherwise
|
230
|
+
def error?
|
231
|
+
status_code == ERROR || status_code == NON_DELIVERY
|
232
|
+
end
|
233
|
+
|
234
|
+
# Was last operation status CONTINUE?
|
235
|
+
#
|
236
|
+
# === Return
|
237
|
+
# true:: If status is CONTINUE
|
238
|
+
# false:: Otherwise
|
239
|
+
def continue?
|
240
|
+
status_code == CONTINUE
|
241
|
+
end
|
242
|
+
|
243
|
+
# Was last operation status RETRY?
|
244
|
+
#
|
245
|
+
# === Return
|
246
|
+
# true:: If status is RETRY
|
247
|
+
# false:: Otherwise
|
248
|
+
def retry?
|
249
|
+
status_code == RETRY
|
250
|
+
end
|
251
|
+
|
252
|
+
# Was last operation status NON_DELIVERY?
|
253
|
+
#
|
254
|
+
# === Return
|
255
|
+
# true:: If status is NON_DELIVERY
|
256
|
+
# false:: Otherwise
|
257
|
+
def non_delivery?
|
258
|
+
status_code == NON_DELIVERY
|
259
|
+
end
|
260
|
+
|
261
|
+
# Was last operation status MULTICAST?
|
262
|
+
# Deprecated for agents at version 13 or above
|
263
|
+
#
|
264
|
+
# === Return
|
265
|
+
# true:: If status is MULTICAST
|
266
|
+
# false:: Otherwise
|
267
|
+
def multicast?
|
268
|
+
status_code == MULTICAST
|
269
|
+
end
|
270
|
+
|
271
|
+
# Was last operation status CANCEL?
|
272
|
+
#
|
273
|
+
# === Return
|
274
|
+
# true:: If status is CANCEL
|
275
|
+
# false:: Otherwise
|
276
|
+
def cancel?
|
277
|
+
status_code == CANCEL
|
278
|
+
end
|
279
|
+
|
280
|
+
# Array of serialized fields given to constructor
|
281
|
+
def serialized_members
|
282
|
+
[@status_code, @content]
|
283
|
+
end
|
284
|
+
|
285
|
+
end # OperationResult
|
286
|
+
|
287
|
+
# Helper module to simplify result construction
|
288
|
+
module OperationResultHelper
|
289
|
+
|
290
|
+
def success_result(*args) OperationResult.success(*args) end
|
291
|
+
def error_result(*args) OperationResult.error(*args) end
|
292
|
+
def continue_result(*args) OperationResult.continue(*args) end
|
293
|
+
def retry_result(*args) OperationResult.retry(*args) end
|
294
|
+
def non_delivery_result(*args) OperationResult.non_delivery(*args) end
|
295
|
+
def cancel_result(*args) OperationResult.cancel(*args) end
|
296
|
+
def result_from(*args) OperationResult.from_results(*args) end
|
297
|
+
|
298
|
+
end # OperationResultHelper
|
299
|
+
|
300
|
+
end # RightScale
|
@@ -0,0 +1,673 @@
|
|
1
|
+
# Copyright (c) 2009-2012 RightScale Inc
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
|
23
|
+
# Hack to replace the Nanite namespace from downrev agents with the RightScale namespace
|
24
|
+
module JSON
|
25
|
+
class << self
|
26
|
+
def parse(source, opts = {})
|
27
|
+
# In gem version this options is set to true by default
|
28
|
+
# but in ruby native json library is set to false by default
|
29
|
+
# Explicitly set it to true so both json libraries act the same
|
30
|
+
opts[:create_additions] = true
|
31
|
+
if source =~ /(.*)json_class":"Nanite::(.*)/
|
32
|
+
JSON.parser.new( Regexp.last_match(1) + 'json_class":"RightScale::' + Regexp.last_match(2), opts).parse
|
33
|
+
else
|
34
|
+
JSON.parser.new(source, opts).parse
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
module RightScale
|
42
|
+
|
43
|
+
# Base class for all packets flowing through the RightNet routers
|
44
|
+
# Knows how to dump itself to MessagePack or JSON
|
45
|
+
class Packet
|
46
|
+
|
47
|
+
# Current version of protocol
|
48
|
+
VERSION = AgentConfig.protocol_version
|
49
|
+
|
50
|
+
# Default version for packet senders unaware of this versioning
|
51
|
+
DEFAULT_VERSION = 0
|
52
|
+
|
53
|
+
# Shard scope value meaning restrict sending request only to agents with no shard id
|
54
|
+
GLOBAL = 0
|
55
|
+
|
56
|
+
# Instance variables that are not serialized because they are only used locally
|
57
|
+
NOT_SERIALIZED = ["received_at"]
|
58
|
+
|
59
|
+
# (Float) Time in seconds in Unix-epoch when message was received
|
60
|
+
attr_accessor :received_at
|
61
|
+
|
62
|
+
# (Integer) Size of packet in bytes
|
63
|
+
attr_accessor :size
|
64
|
+
|
65
|
+
def initialize
|
66
|
+
raise NotImplementedError.new("#{self.class.name} is an abstract class.")
|
67
|
+
end
|
68
|
+
|
69
|
+
# Create packet from unmarshalled MessagePack data
|
70
|
+
#
|
71
|
+
# === Parameters
|
72
|
+
# o(Hash):: MessagePack data
|
73
|
+
#
|
74
|
+
# === Return
|
75
|
+
# (Packet):: New packet
|
76
|
+
def self.msgpack_create(o)
|
77
|
+
create(o)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Create packet from unmarshalled JSON data
|
81
|
+
#
|
82
|
+
# === Parameters
|
83
|
+
# o(Hash):: MessagePack data
|
84
|
+
#
|
85
|
+
# === Return
|
86
|
+
# (Packet):: New packet
|
87
|
+
def self.json_create(o)
|
88
|
+
create(o)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Marshal packet into MessagePack format
|
92
|
+
#
|
93
|
+
# === Parameters
|
94
|
+
# a(Array):: Arguments
|
95
|
+
#
|
96
|
+
# === Return
|
97
|
+
# msg(String):: Marshalled packet
|
98
|
+
def to_msgpack(*a)
|
99
|
+
msg = {
|
100
|
+
'msgpack_class' => self.class.name,
|
101
|
+
'data' => instance_variables.inject({}) do |m, ivar|
|
102
|
+
name = ivar.to_s.sub(/@/, '')
|
103
|
+
m[name] = instance_variable_get(ivar) unless NOT_SERIALIZED.include?(name)
|
104
|
+
m
|
105
|
+
end,
|
106
|
+
'size' => nil
|
107
|
+
}.to_msgpack(*a)
|
108
|
+
@size = msg.size
|
109
|
+
# For ruby 1.9 size attribute moves from front to back of packet
|
110
|
+
re = RUBY_VERSION < "1.9.0" ? /size\xC0/ : /size\xC0$/
|
111
|
+
# For msgpack 0.5.1 the to_msgpack result is a MessagePack::Packer so need to convert to string
|
112
|
+
msg = msg.to_s.sub!(re) { |m| "size" + @size.to_msgpack }
|
113
|
+
msg
|
114
|
+
end
|
115
|
+
|
116
|
+
# Marshal packet into JSON format
|
117
|
+
#
|
118
|
+
# === Parameters
|
119
|
+
# a(Array):: Arguments
|
120
|
+
#
|
121
|
+
# === Return
|
122
|
+
# js(String):: Marshalled packet
|
123
|
+
def to_json(*a)
|
124
|
+
# Hack to override RightScale namespace with Nanite for downward compatibility
|
125
|
+
class_name = self.class.name
|
126
|
+
if class_name =~ /^RightScale::(.*)/
|
127
|
+
class_name = "Nanite::" + Regexp.last_match(1)
|
128
|
+
end
|
129
|
+
|
130
|
+
js = {
|
131
|
+
'json_class' => class_name,
|
132
|
+
'data' => instance_variables.inject({}) do |m, ivar|
|
133
|
+
name = ivar.to_s.sub(/@/, '')
|
134
|
+
m[name] = instance_variable_get(ivar) unless NOT_SERIALIZED.include?(name)
|
135
|
+
m
|
136
|
+
end
|
137
|
+
}.to_json(*a)
|
138
|
+
@size = js.size
|
139
|
+
js = js.chop + ",\"size\":#{@size}}"
|
140
|
+
end
|
141
|
+
|
142
|
+
# Name of packet in lower snake case
|
143
|
+
#
|
144
|
+
# === Return
|
145
|
+
# (String):: Packet name
|
146
|
+
def name
|
147
|
+
self.class.to_s.split('::').last.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
|
148
|
+
end
|
149
|
+
|
150
|
+
# Generate log representation
|
151
|
+
#
|
152
|
+
# === Parameters
|
153
|
+
# filter(Array(Symbol)):: Attributes to be included in output
|
154
|
+
# version(Symbol|nil):: Version to display: :recv_version, :send_version, or nil meaning none
|
155
|
+
#
|
156
|
+
# === Return
|
157
|
+
# log_msg(String):: Log representation
|
158
|
+
def to_s(filter = nil, version = nil)
|
159
|
+
v = send(version) if version
|
160
|
+
v = (v && v != DEFAULT_VERSION) ? " v#{v}" : ""
|
161
|
+
log_msg = "[#{name}#{v}]"
|
162
|
+
duration = if @duration && (filter.nil? || filter.include?(:duration))
|
163
|
+
", #{enough_precision(@duration)} sec"
|
164
|
+
elsif @received_at && (filter.nil? || filter.include?(:local_duration))
|
165
|
+
", #{enough_precision(Time.now.to_f - @received_at)} sec"
|
166
|
+
end
|
167
|
+
log_msg += " (#{@size.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")} bytes#{duration})" if @size && !@size.to_s.empty?
|
168
|
+
log_msg
|
169
|
+
end
|
170
|
+
|
171
|
+
# Determine enough precision for floating point value to give at least two significant
|
172
|
+
# digits and then convert the value to a decimal digit string of that precision
|
173
|
+
#
|
174
|
+
# === Parameters
|
175
|
+
# value(Float):: Value to be converted
|
176
|
+
#
|
177
|
+
# === Return
|
178
|
+
# (String):: Floating point digit string
|
179
|
+
def enough_precision(value)
|
180
|
+
scale = [1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0]
|
181
|
+
enough = lambda { |v| (v >= 10.0 ? 0 :
|
182
|
+
(v >= 1.0 ? 1 :
|
183
|
+
(v >= 0.1 ? 2 :
|
184
|
+
(v >= 0.01 ? 3 :
|
185
|
+
(v > 0.001 ? 4 :
|
186
|
+
(v > 0.0 ? 5 : 0)))))) }
|
187
|
+
digit_str = lambda { |p, v| sprintf("%.#{p}f", (v * scale[p]).round / scale[p])}
|
188
|
+
digit_str.call(enough.call(value), value)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Generate log friendly serialized identity
|
192
|
+
# Result marked with leading '*' if not same as original identity
|
193
|
+
#
|
194
|
+
# === Parameters
|
195
|
+
# id(String):: Serialized identity
|
196
|
+
#
|
197
|
+
# === Return
|
198
|
+
# (String):: Log friendly serialized identity
|
199
|
+
def id_to_s(id)
|
200
|
+
modified_id = AgentIdentity.compatible_serialized(id)
|
201
|
+
if id == modified_id then modified_id else "*#{modified_id}" end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Generate log friendly serialized identity for one or more ids
|
205
|
+
# Limit to 1000 bytes
|
206
|
+
#
|
207
|
+
# === Parameters
|
208
|
+
# ids(Array|String):: Serialized identity or array of serialized identities
|
209
|
+
#
|
210
|
+
# === Return
|
211
|
+
# (String):: Log friendly serialized identity
|
212
|
+
def ids_to_s(ids)
|
213
|
+
if ids.is_a?(Array)
|
214
|
+
s = ids.each { |i| id_to_s(i) }.join(', ')
|
215
|
+
s.size > 1000 ? "[#{s[0, 1000]}...]" : "[#{s}]"
|
216
|
+
else
|
217
|
+
id_to_s(ids)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# Convert serialized AgentIdentity to compatible format
|
222
|
+
#
|
223
|
+
# === Parameters
|
224
|
+
# id(String):: Serialized identity
|
225
|
+
#
|
226
|
+
# === Return
|
227
|
+
# (String):: Compatible serialized identity
|
228
|
+
def self.compatible(id)
|
229
|
+
AgentIdentity.compatible_serialized(id)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Get target to be used for encrypting the packet
|
233
|
+
#
|
234
|
+
# === Return
|
235
|
+
# (String):: Target
|
236
|
+
def target_for_encryption
|
237
|
+
nil
|
238
|
+
end
|
239
|
+
|
240
|
+
# Whether the packet is one that does not have an associated response
|
241
|
+
#
|
242
|
+
# === Return
|
243
|
+
# (Boolean):: Defaults to true
|
244
|
+
def one_way
|
245
|
+
true
|
246
|
+
end
|
247
|
+
|
248
|
+
# Generate token used to trace execution of operation across multiple packets
|
249
|
+
#
|
250
|
+
# === Return
|
251
|
+
# tr(String):: Trace token, may be empty
|
252
|
+
def trace
|
253
|
+
audit_id = self.respond_to?(:payload) && payload.is_a?(Hash) && (payload['audit_id'] || payload[:audit_id])
|
254
|
+
tok = self.respond_to?(:token) && token
|
255
|
+
tr = "<#{audit_id || nil}> <#{tok}>"
|
256
|
+
end
|
257
|
+
|
258
|
+
# Retrieve protocol version of original creator of packet
|
259
|
+
#
|
260
|
+
# === Return
|
261
|
+
# (Integer) Received protocol version
|
262
|
+
def recv_version
|
263
|
+
@version[0]
|
264
|
+
end
|
265
|
+
|
266
|
+
# Retrieve protocol version of packet for use when sending packet
|
267
|
+
#
|
268
|
+
# === Return
|
269
|
+
# (Integer) Send protocol version
|
270
|
+
def send_version
|
271
|
+
@version[1]
|
272
|
+
end
|
273
|
+
|
274
|
+
# Set protocol version of packet for use when sending packet
|
275
|
+
def send_version=(value)
|
276
|
+
@version[1] = value
|
277
|
+
end
|
278
|
+
|
279
|
+
end # Packet
|
280
|
+
|
281
|
+
|
282
|
+
# Packet for a work request for an actor node that has an expected result
|
283
|
+
class Request < Packet
|
284
|
+
|
285
|
+
attr_accessor :from, :scope, :payload, :type, :token, :reply_to, :selector, :target, :persistent, :expires_at,
|
286
|
+
:tags, :tries
|
287
|
+
|
288
|
+
DEFAULT_OPTIONS = {:selector => :any}
|
289
|
+
|
290
|
+
# Create packet
|
291
|
+
#
|
292
|
+
# === Parameters
|
293
|
+
# type(String):: Dispatch route for the request
|
294
|
+
# payload(Any):: Arbitrary data that is transferred to actor
|
295
|
+
# opts(Hash):: Optional settings:
|
296
|
+
# :from(String):: Sender identity
|
297
|
+
# :scope(Hash):: Define behavior that should be used to resolve tag based routing
|
298
|
+
# :token(String):: Generated request id that a router uses to identify replies
|
299
|
+
# :reply_to(String):: Identity of the node that actor replies to, usually a router itself
|
300
|
+
# :selector(Symbol):: Selector used to route the request: :any or :all, defaults to :any,
|
301
|
+
# :all deprecated for version 13 and above
|
302
|
+
# :target(String|Array):: Target recipient(s)
|
303
|
+
# :persistent(Boolean):: Indicates if this request should be saved to persistent storage
|
304
|
+
# by the AMQP broker
|
305
|
+
# :expires_at(Integer|nil):: Time in seconds in Unix-epoch when this request expires and
|
306
|
+
# is to be ignored by the receiver; value 0 means never expire; defaults to 0
|
307
|
+
# :tags(Array(Symbol)):: List of tags to be used for selecting target for this request
|
308
|
+
# :tries(Array):: List of tokens for previous attempts to send this request
|
309
|
+
# version(Array):: Protocol version of the original creator of the packet followed by the
|
310
|
+
# protocol version of the packet contents to be used when sending
|
311
|
+
# size(Integer):: Size of request in bytes used only for marshalling
|
312
|
+
def initialize(type, payload, opts = {}, version = [VERSION, VERSION], size = nil)
|
313
|
+
opts = DEFAULT_OPTIONS.merge(opts)
|
314
|
+
@type = type
|
315
|
+
@payload = payload
|
316
|
+
@from = opts[:from]
|
317
|
+
@scope = opts[:scope]
|
318
|
+
@token = opts[:token]
|
319
|
+
@reply_to = opts[:reply_to]
|
320
|
+
@selector = opts[:selector]
|
321
|
+
@selector = :any if ["least_loaded", "random"].include?(@selector.to_s)
|
322
|
+
@target = opts[:target]
|
323
|
+
@persistent = opts[:persistent]
|
324
|
+
@expires_at = opts[:expires_at] || 0
|
325
|
+
@tags = opts[:tags] || []
|
326
|
+
@tries = opts[:tries] || []
|
327
|
+
@version = version
|
328
|
+
@size = size
|
329
|
+
end
|
330
|
+
|
331
|
+
# Test whether the request is being fanned out to multiple targets
|
332
|
+
#
|
333
|
+
# === Return
|
334
|
+
# (Boolean):: true if is multicast, otherwise false
|
335
|
+
def fanout?
|
336
|
+
@selector.to_s == 'all'
|
337
|
+
end
|
338
|
+
|
339
|
+
# Create packet from unmarshalled data
|
340
|
+
#
|
341
|
+
# === Parameters
|
342
|
+
# o(Hash):: Unmarshalled data
|
343
|
+
#
|
344
|
+
# === Return
|
345
|
+
# (Request):: New packet
|
346
|
+
def self.create(o)
|
347
|
+
i = o['data']
|
348
|
+
expires_at = if i.has_key?('created_at')
|
349
|
+
created_at = i['created_at'].to_i
|
350
|
+
created_at > 0 ? created_at + (15 * 60) : 0
|
351
|
+
else
|
352
|
+
i['expires_at']
|
353
|
+
end
|
354
|
+
new(i['type'], i['payload'], { :from => self.compatible(i['from']), :scope => i['scope'],
|
355
|
+
:token => i['token'], :reply_to => self.compatible(i['reply_to']),
|
356
|
+
:selector => i['selector'], :target => self.compatible(i['target']),
|
357
|
+
:persistent => i['persistent'], :tags => i['tags'],
|
358
|
+
:expires_at => expires_at, :tries => i['tries'] },
|
359
|
+
i['version'] || [DEFAULT_VERSION, DEFAULT_VERSION], o['size'])
|
360
|
+
end
|
361
|
+
|
362
|
+
# Generate log representation
|
363
|
+
#
|
364
|
+
# === Parameters
|
365
|
+
# filter(Array(Symbol)):: Attributes to be included in output
|
366
|
+
# version(Symbol|nil):: Version to display: :recv_version, :send_version, or nil meaning none
|
367
|
+
#
|
368
|
+
# === Return
|
369
|
+
# log_msg(String):: Log representation
|
370
|
+
def to_s(filter = nil, version = nil)
|
371
|
+
payload = PayloadFormatter.log(@type, @payload)
|
372
|
+
log_msg = "#{super(filter, version)} #{trace} #{@type}"
|
373
|
+
log_msg += " #{payload}" if payload
|
374
|
+
log_msg += " from #{id_to_s(@from)}" if filter.nil? || filter.include?(:from)
|
375
|
+
log_msg += ", target #{ids_to_s(@target)}" if @target && (filter.nil? || filter.include?(:target))
|
376
|
+
log_msg += ", scope #{@scope.inspect}" if @scope && (filter.nil? || filter.include?(:scope))
|
377
|
+
log_msg += ", fanout" if (filter.nil? || filter.include?(:fanout)) && fanout?
|
378
|
+
log_msg += ", reply_to #{id_to_s(@reply_to)}" if @reply_to && (filter.nil? || filter.include?(:reply_to))
|
379
|
+
log_msg += ", tags #{@tags.inspect}" if @tags && !@tags.empty? && (filter.nil? || filter.include?(:tags))
|
380
|
+
log_msg += ", persistent" if @persistent && (filter.nil? || filter.include?(:persistent))
|
381
|
+
log_msg += ", tries #{tries_to_s}" if @tries && !@tries.empty? && (filter.nil? || filter.include?(:tries))
|
382
|
+
log_msg += ", payload #{@payload.inspect}" if filter && filter.include?(:payload)
|
383
|
+
log_msg
|
384
|
+
end
|
385
|
+
|
386
|
+
# Convert tries list to string representation
|
387
|
+
#
|
388
|
+
# === Return
|
389
|
+
# log_msg(String):: Tries list
|
390
|
+
def tries_to_s
|
391
|
+
@tries.map { |t| "<#{t}>" }.join(", ")
|
392
|
+
end
|
393
|
+
|
394
|
+
# Get target to be used for encrypting the packet
|
395
|
+
#
|
396
|
+
# === Return
|
397
|
+
# (String):: Target
|
398
|
+
def target_for_encryption
|
399
|
+
@target
|
400
|
+
end
|
401
|
+
|
402
|
+
# Whether the packet is one that does not have an associated response
|
403
|
+
#
|
404
|
+
# === Return
|
405
|
+
# false:: Always return false
|
406
|
+
def one_way
|
407
|
+
false
|
408
|
+
end
|
409
|
+
|
410
|
+
end # Request
|
411
|
+
|
412
|
+
|
413
|
+
# Packet for a work request for an actor node that has no result, i.e., one-way request
|
414
|
+
class Push < Packet
|
415
|
+
|
416
|
+
attr_accessor :from, :scope, :payload, :type, :token, :selector, :target, :persistent, :confirm,
|
417
|
+
:expires_at, :tags
|
418
|
+
|
419
|
+
DEFAULT_OPTIONS = {:selector => :any}
|
420
|
+
|
421
|
+
# Create packet
|
422
|
+
#
|
423
|
+
# === Parameters
|
424
|
+
# type(String):: Dispatch route for the request
|
425
|
+
# payload(Any):: Arbitrary data that is transferred to actor
|
426
|
+
# opts(Hash):: Optional settings:
|
427
|
+
# :from(String):: Sender identity
|
428
|
+
# :scope(Hash):: Define behavior that should be used to resolve tag based routing
|
429
|
+
# :token(String):: Generated request id that a router uses to identify replies
|
430
|
+
# :selector(Symbol):: Selector used to route the request: :any or :all, defaults to :any
|
431
|
+
# :target(String|Array):: Target recipient(s)
|
432
|
+
# :persistent(Boolean):: Indicates if this request should be saved to persistent storage
|
433
|
+
# by the AMQP broker
|
434
|
+
# :confirm(Boolean):: Whether require confirmation response from router containing targets
|
435
|
+
# to which request was published but not necessarily delivered
|
436
|
+
# :expires_at(Integer|nil):: Time in seconds in Unix-epoch when this request expires and
|
437
|
+
# is to be ignored by the receiver; value 0 means never expire; defaults to 0
|
438
|
+
# :tags(Array(Symbol)):: List of tags to be used for selecting target for this request
|
439
|
+
# version(Array):: Protocol version of the original creator of the packet followed by the
|
440
|
+
# protocol version of the packet contents to be used when sending
|
441
|
+
# size(Integer):: Size of request in bytes used only for marshalling
|
442
|
+
def initialize(type, payload, opts = {}, version = [VERSION, VERSION], size = nil)
|
443
|
+
opts = DEFAULT_OPTIONS.merge(opts)
|
444
|
+
@type = type
|
445
|
+
@payload = payload
|
446
|
+
@from = opts[:from]
|
447
|
+
@scope = opts[:scope]
|
448
|
+
@token = opts[:token]
|
449
|
+
@selector = opts[:selector]
|
450
|
+
@selector = :any if ["least_loaded", "random"].include?(@selector.to_s)
|
451
|
+
@target = opts[:target]
|
452
|
+
@persistent = opts[:persistent]
|
453
|
+
@confirm = opts[:confirm]
|
454
|
+
@expires_at = opts[:expires_at] || 0
|
455
|
+
@tags = opts[:tags] || []
|
456
|
+
@version = version
|
457
|
+
@size = size
|
458
|
+
end
|
459
|
+
|
460
|
+
# Test whether the request is being fanned out to multiple targets
|
461
|
+
#
|
462
|
+
# === Return
|
463
|
+
# (Boolean):: true if is fanout, otherwise false
|
464
|
+
def fanout?
|
465
|
+
@selector.to_s == 'all'
|
466
|
+
end
|
467
|
+
|
468
|
+
# Keep interface consistent with Request packets
|
469
|
+
# A push never gets retried
|
470
|
+
#
|
471
|
+
# === Return
|
472
|
+
# []:: Always return empty array
|
473
|
+
def tries
|
474
|
+
[]
|
475
|
+
end
|
476
|
+
|
477
|
+
# Create packet from unmarshalled data
|
478
|
+
#
|
479
|
+
# === Parameters
|
480
|
+
# o(Hash):: Unmarshalled data
|
481
|
+
#
|
482
|
+
# === Return
|
483
|
+
# (Push):: New packet
|
484
|
+
def self.create(o)
|
485
|
+
i = o['data']
|
486
|
+
new(i['type'], i['payload'], { :from => self.compatible(i['from']), :scope => i['scope'],
|
487
|
+
:token => i['token'], :selector => i['selector'],
|
488
|
+
:target => self.compatible(i['target']), :persistent => i['persistent'],
|
489
|
+
:confirm => i['confirm'], :expires_at => i['expires_at'],
|
490
|
+
:tags => i['tags']},
|
491
|
+
i['version'] || [DEFAULT_VERSION, DEFAULT_VERSION], o['size'])
|
492
|
+
end
|
493
|
+
|
494
|
+
# Generate log representation
|
495
|
+
#
|
496
|
+
# === Parameters
|
497
|
+
# filter(Array(Symbol)):: Attributes to be included in output
|
498
|
+
# version(Symbol|nil):: Version to display: :recv_version, :send_version, or nil meaning none
|
499
|
+
#
|
500
|
+
# === Return
|
501
|
+
# log_msg(String):: Log representation
|
502
|
+
def to_s(filter = nil, version = nil)
|
503
|
+
payload = PayloadFormatter.log(@type, @payload)
|
504
|
+
log_msg = "#{super(filter, version)} #{trace} #{@type}"
|
505
|
+
log_msg += " #{payload}" if payload
|
506
|
+
log_msg += " from #{id_to_s(@from)}" if filter.nil? || filter.include?(:from)
|
507
|
+
log_msg += ", target #{ids_to_s(@target)}" if @target && (filter.nil? || filter.include?(:target))
|
508
|
+
log_msg += ", scope #{@scope.inspect}" if @scope && (filter.nil? || filter.include?(:scope))
|
509
|
+
log_msg += ", fanout" if (filter.nil? || filter.include?(:fanout)) && fanout?
|
510
|
+
log_msg += ", tags #{@tags.inspect}" if @tags && !@tags.empty? && (filter.nil? || filter.include?(:tags))
|
511
|
+
log_msg += ", persistent" if @persistent && (filter.nil? || filter.include?(:persistent))
|
512
|
+
log_msg += ", payload #{@payload.inspect}" if filter && filter.include?(:payload)
|
513
|
+
log_msg
|
514
|
+
end
|
515
|
+
|
516
|
+
# Get target to be used for encrypting the packet
|
517
|
+
#
|
518
|
+
# === Return
|
519
|
+
# (String):: Target
|
520
|
+
def target_for_encryption
|
521
|
+
@target
|
522
|
+
end
|
523
|
+
|
524
|
+
end # Push
|
525
|
+
|
526
|
+
|
527
|
+
# Packet for a work result notification sent from actor node
|
528
|
+
class Result < Packet
|
529
|
+
|
530
|
+
attr_accessor :token, :results, :to, :from, :request_from, :tries, :persistent, :duration
|
531
|
+
|
532
|
+
# Create packet
|
533
|
+
#
|
534
|
+
# === Parameters
|
535
|
+
# token(String):: Generated request id that a router uses to identify replies
|
536
|
+
# to(String):: Identity of the node to which result should be delivered
|
537
|
+
# results(Any):: Arbitrary data that is transferred from actor, a result of actor's work
|
538
|
+
# from(String):: Sender identity
|
539
|
+
# request_from(String):: Identity of the agent that sent the original request
|
540
|
+
# tries(Array):: List of tokens for previous attempts to send associated request
|
541
|
+
# persistent(Boolean):: Indicates if this result should be saved to persistent storage
|
542
|
+
# by the AMQP broker
|
543
|
+
# duration(Float):: Number of seconds required to produce the result
|
544
|
+
# version(Array):: Protocol version of the original creator of the packet followed by the
|
545
|
+
# protocol version of the packet contents to be used when sending
|
546
|
+
# size(Integer):: Size of request in bytes used only for marshalling
|
547
|
+
def initialize(token, to, results, from, request_from = nil, tries = nil, persistent = nil, duration = nil,
|
548
|
+
version = [VERSION, VERSION], size = nil)
|
549
|
+
@token = token
|
550
|
+
@to = to
|
551
|
+
@results = results
|
552
|
+
@from = from
|
553
|
+
@request_from = request_from
|
554
|
+
@tries = tries || []
|
555
|
+
@persistent = persistent
|
556
|
+
@duration = duration
|
557
|
+
@version = version
|
558
|
+
@size = size
|
559
|
+
end
|
560
|
+
|
561
|
+
# Create packet from unmarshalled data
|
562
|
+
#
|
563
|
+
# === Parameters
|
564
|
+
# o(Hash):: Unmarshalled data
|
565
|
+
#
|
566
|
+
# === Return
|
567
|
+
# (Result):: New packet
|
568
|
+
def self.create(o)
|
569
|
+
i = o['data']
|
570
|
+
new(i['token'], self.compatible(i['to']), i['results'], self.compatible(i['from']),
|
571
|
+
self.compatible(i['request_from']), i['tries'], i['persistent'], i['duration'],
|
572
|
+
i['version'] || [DEFAULT_VERSION, DEFAULT_VERSION], o['size'])
|
573
|
+
end
|
574
|
+
|
575
|
+
# Generate log representation
|
576
|
+
#
|
577
|
+
# === Parameters
|
578
|
+
# filter(Array(Symbol)):: Attributes to be included in output
|
579
|
+
# version(Symbol|nil):: Version to display: :recv_version, :send_version, or nil meaning none
|
580
|
+
#
|
581
|
+
# === Return
|
582
|
+
# log_msg(String):: Log representation
|
583
|
+
def to_s(filter = nil, version = nil)
|
584
|
+
log_msg = "#{super(filter, version)} #{trace}"
|
585
|
+
log_msg += " from #{id_to_s(@from)}" if filter.nil? || filter.include?(:from)
|
586
|
+
log_msg += " to #{id_to_s(@to)}" if filter.nil? || filter.include?(:to)
|
587
|
+
log_msg += ", request_from #{id_to_s(@request_from)}" if @request_from && (filter.nil? || filter.include?(:request_from))
|
588
|
+
log_msg += ", persistent" if @persistent && (filter.nil? || filter.include?(:persistent))
|
589
|
+
log_msg += ", tries #{tries_to_s}" if @tries && !@tries.empty? && (filter.nil? || filter.include?(:tries))
|
590
|
+
if filter.nil? || !filter.include?(:results)
|
591
|
+
if !@results.nil?
|
592
|
+
if @results.is_a?(RightScale::OperationResult) # Will be true when logging a 'SEND'
|
593
|
+
res = @results
|
594
|
+
elsif @results.is_a?(Hash) && @results.size == 1 # Will be true when logging a 'RECV' for version 9 or below
|
595
|
+
res = @results.values.first
|
596
|
+
end
|
597
|
+
log_msg += " #{res.to_s}" if res
|
598
|
+
end
|
599
|
+
else
|
600
|
+
log_msg += " results #{@results.inspect}"
|
601
|
+
end
|
602
|
+
log_msg
|
603
|
+
end
|
604
|
+
|
605
|
+
# Convert tries list to string representation
|
606
|
+
#
|
607
|
+
# === Return
|
608
|
+
# log_msg(String):: Tries list
|
609
|
+
def tries_to_s
|
610
|
+
log_msg = ""
|
611
|
+
@tries.each { |r| log_msg += "<#{r}>, " }
|
612
|
+
log_msg = log_msg[0..-3] if log_msg.size > 1
|
613
|
+
end
|
614
|
+
|
615
|
+
# Get target to be used for encrypting the packet
|
616
|
+
#
|
617
|
+
# === Return
|
618
|
+
# (String):: Target
|
619
|
+
def target_for_encryption
|
620
|
+
@to
|
621
|
+
end
|
622
|
+
|
623
|
+
end # Result
|
624
|
+
|
625
|
+
|
626
|
+
# Packet for carrying statistics
|
627
|
+
class Stats < Packet
|
628
|
+
|
629
|
+
attr_accessor :data, :token, :from
|
630
|
+
|
631
|
+
# Create packet
|
632
|
+
#
|
633
|
+
# === Parameters
|
634
|
+
# data(Object):: Data
|
635
|
+
# from(String):: Identity of sender
|
636
|
+
# version(Array):: Protocol version of the original creator of the packet followed by the
|
637
|
+
# protocol version of the packet contents to be used when sending
|
638
|
+
# size(Integer):: Size of request in bytes used only for marshalling
|
639
|
+
def initialize(data, from, version = [VERSION, VERSION], size = nil)
|
640
|
+
@data = data
|
641
|
+
@from = from
|
642
|
+
@version = version
|
643
|
+
@size = size
|
644
|
+
end
|
645
|
+
|
646
|
+
# Create packet from unmarshalled data
|
647
|
+
#
|
648
|
+
# === Parameters
|
649
|
+
# o(Hash):: Unmarshalled data
|
650
|
+
#
|
651
|
+
# === Return
|
652
|
+
# (Result):: New packet
|
653
|
+
def self.create(o)
|
654
|
+
i = o['data']
|
655
|
+
new(i['data'], self.compatible(i['from']), i['version'] || [DEFAULT_VERSION, DEFAULT_VERSION], o['size'])
|
656
|
+
end
|
657
|
+
|
658
|
+
# Generate log representation
|
659
|
+
#
|
660
|
+
# === Parameters
|
661
|
+
# filter(Array(Symbol)):: Attributes to be included in output
|
662
|
+
# version(Symbol|nil):: Version to display: :recv_version, :send_version, or nil meaning none
|
663
|
+
#
|
664
|
+
# === Return
|
665
|
+
# log_msg(String):: Log representation
|
666
|
+
def to_s(filter = nil, version = nil)
|
667
|
+
log_msg = "#{super(filter, version)} #{id_to_s(@from)}"
|
668
|
+
end
|
669
|
+
|
670
|
+
end # Stats
|
671
|
+
|
672
|
+
end # RightScale
|
673
|
+
|