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,27 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 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
|
+
# it's useful to auto-flush console output on Windows where it would otherwise
|
24
|
+
# be unavailable from a ruby process which was hanging (our code would never
|
25
|
+
# hang, of course). this is consistent with Powershell's auto-flush behavior.
|
26
|
+
STDOUT.sync = true
|
27
|
+
STDERR.sync = true
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 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
|
+
require 'rubygems'
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'windows/time'
|
27
|
+
|
28
|
+
# monkey patch Time.now because Windows Ruby interpreters used the wrong API
|
29
|
+
# and queried local time instead of UTC time prior to Ruby v1.9.1. This
|
30
|
+
# made the Ruby 1.8.x interpreters vulnerable to external changes to
|
31
|
+
# timezone which cause Time.now to return times which are offset from from the
|
32
|
+
# correct value. This implementation is borrowed from the C source for Ruby
|
33
|
+
# v1.9.1 from www.ruby-lang.org ("win32/win32.c").
|
34
|
+
if RUBY_VERSION < "1.9.1"
|
35
|
+
class Time
|
36
|
+
def self.now
|
37
|
+
# query UTC time as a 64-bit ularge value.
|
38
|
+
filetime = 0.chr * 8
|
39
|
+
::Windows::Time::GetSystemTimeAsFileTime.call(filetime)
|
40
|
+
low_date_time = filetime[0,4].unpack('V')[0]
|
41
|
+
high_date_time = filetime[4,4].unpack('V')[0]
|
42
|
+
value = high_date_time * 0x100000000 + low_date_time
|
43
|
+
|
44
|
+
# value is now 100-nanosec intervals since 1601/01/01 00:00:00 UTC,
|
45
|
+
# convert it into UNIX time (since 1970/01/01 00:00:00 UTC).
|
46
|
+
value /= 10 # 100-nanoseconds to microseconds
|
47
|
+
microseconds = 1000 * 1000
|
48
|
+
value -= ((1970 - 1601) * 365.2425).to_i * 24 * 60 * 60 * microseconds
|
49
|
+
return Time.at(value / microseconds, value % microseconds)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
rescue LoadError
|
54
|
+
# ignore load error and skip monkey-patch if gems are not yet installed.
|
55
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 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
|
+
require 'rubygems'
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'win32ole'
|
27
|
+
|
28
|
+
# ohai 0.3.6 has a bug which causes WMI data to be imported using the default
|
29
|
+
# Windows code page. the workaround is to set the win32ole gem's code page to
|
30
|
+
# UTF-8, which is probably a good general Ruby on Windows practice in any case.
|
31
|
+
WIN32OLE.codepage = WIN32OLE::CP_UTF8
|
32
|
+
rescue LoadError
|
33
|
+
# ignore load error and skip monkey-patch if gems are not yet installed.
|
34
|
+
end
|
@@ -0,0 +1,102 @@
|
|
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
|
+
# Apply each method call to all registered targets
|
26
|
+
class Multiplexer
|
27
|
+
|
28
|
+
# Access to underlying multiplexed objects
|
29
|
+
attr_reader :targets
|
30
|
+
|
31
|
+
# Undefine warn to prevent Kernel#warn from being called
|
32
|
+
undef warn rescue nil
|
33
|
+
|
34
|
+
# Initialize multiplexer targets
|
35
|
+
#
|
36
|
+
# === Parameters
|
37
|
+
# targets(Object):: Targets that should receive the method calls
|
38
|
+
def initialize(*targets)
|
39
|
+
@targets = targets || []
|
40
|
+
end
|
41
|
+
|
42
|
+
# Add object to list of multiplexed targets
|
43
|
+
#
|
44
|
+
# === Parameters
|
45
|
+
# target(Object):: Add target to list of multiplexed targets
|
46
|
+
#
|
47
|
+
# === Return
|
48
|
+
# self(RightScale::Multiplexer):: self so operation can be chained
|
49
|
+
def add(target)
|
50
|
+
@targets << target unless @targets.include?(target)
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
# Remove object from list of multiplexed targets
|
55
|
+
#
|
56
|
+
# === Parameters
|
57
|
+
# target(Object):: Remove target from list of multiplexed targets
|
58
|
+
#
|
59
|
+
# === Return
|
60
|
+
# self(RightScale::Multiplexer):: self so operation can be chained
|
61
|
+
def remove(target)
|
62
|
+
@targets.delete_if { |t| t == target }
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# Access target at given index
|
67
|
+
#
|
68
|
+
# === Parameters
|
69
|
+
# index(Integer):: Target index
|
70
|
+
#
|
71
|
+
# === Return
|
72
|
+
# target(Object):: Target at index 'index' or nil if none
|
73
|
+
def [](index)
|
74
|
+
target = @targets[index]
|
75
|
+
end
|
76
|
+
|
77
|
+
# Forward any method invocation to targets
|
78
|
+
#
|
79
|
+
# === Parameters
|
80
|
+
# m(Symbol):: Method that should be multiplexed
|
81
|
+
# args(Array):: Arguments
|
82
|
+
#
|
83
|
+
# === Return
|
84
|
+
# res(Object):: Result of first target in list
|
85
|
+
def method_missing(m, *args)
|
86
|
+
res = @targets.inject([]) { |res, t| res << t.send(m, *args) }
|
87
|
+
res[0]
|
88
|
+
end
|
89
|
+
|
90
|
+
# Determine whether this object, or ALL of its targets, responds to
|
91
|
+
# the named method.
|
92
|
+
#
|
93
|
+
# === Parameters
|
94
|
+
# m(Symbol):: Forwarded method name
|
95
|
+
#
|
96
|
+
# === Return
|
97
|
+
# (true|false):: True if this object, or ALL targets, respond to the names method; false otherwise
|
98
|
+
def respond_to?(m)
|
99
|
+
super(m) || @targets.all? { |t| t.respond_to?(m) }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,270 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009-2013 RightScale Inc
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
module RightScale
|
24
|
+
|
25
|
+
# Handler for queueing of requests when offline relative to RightNet
|
26
|
+
# and then sending the requests when successfully reconnect
|
27
|
+
class OfflineHandler
|
28
|
+
|
29
|
+
# Maximum seconds to wait before starting flushing offline queue when disabling offline mode
|
30
|
+
MAX_QUEUE_FLUSH_DELAY = 2 * 60
|
31
|
+
|
32
|
+
# Maximum number of offline queued requests before triggering restart vote
|
33
|
+
MAX_QUEUED_REQUESTS = 100
|
34
|
+
|
35
|
+
# Number of seconds that should be spent in offline mode before triggering a restart vote
|
36
|
+
RESTART_VOTE_DELAY = 15 * 60
|
37
|
+
|
38
|
+
# (Symbol) Current queue state with possible values:
|
39
|
+
# Value Description Action Next state
|
40
|
+
# :created Queue created init :initializing
|
41
|
+
# :initializing Agent still initializing start :running
|
42
|
+
# :running Queue has been started disable when offline :flushing
|
43
|
+
# :flushing Sending queued requests enable :running
|
44
|
+
# :terminating Agent terminating
|
45
|
+
attr_reader :state
|
46
|
+
|
47
|
+
# (Symbol) Current offline handling mode with possible values:
|
48
|
+
# Value Description
|
49
|
+
# :initializing Agent still initializing
|
50
|
+
# :online Agent connected
|
51
|
+
# :offline Agent disconnected
|
52
|
+
attr_reader :mode
|
53
|
+
|
54
|
+
# (Array) Offline queue
|
55
|
+
attr_accessor :queue
|
56
|
+
|
57
|
+
# Create offline queueing handler
|
58
|
+
#
|
59
|
+
# === Parameters
|
60
|
+
# restart_callback(Proc):: Callback that is activated on each restart vote with votes being initiated
|
61
|
+
# by offline queue exceeding MAX_QUEUED_REQUESTS
|
62
|
+
# offline_stats(RightSupport::Stats::Activity):: Offline queue tracking statistics
|
63
|
+
def initialize(restart_callback, offline_stats)
|
64
|
+
@restart_vote = restart_callback
|
65
|
+
@restart_vote_timer = nil
|
66
|
+
@restart_vote_count = 0
|
67
|
+
@offline_stats = offline_stats
|
68
|
+
@state = :created
|
69
|
+
@mode = :initializing
|
70
|
+
@queue = []
|
71
|
+
end
|
72
|
+
|
73
|
+
# Initialize the offline queue
|
74
|
+
# All requests sent prior to running this initialization are queued
|
75
|
+
# and then are sent once this initialization has run
|
76
|
+
# All requests following this call and prior to calling start
|
77
|
+
# are prepended to the request queue
|
78
|
+
#
|
79
|
+
# === Return
|
80
|
+
# true:: Always return true
|
81
|
+
def init
|
82
|
+
@state = :initializing if @state == :created
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
# Switch to online mode and send all buffered messages
|
87
|
+
#
|
88
|
+
# === Return
|
89
|
+
# true:: Always return true
|
90
|
+
def start
|
91
|
+
if @state == :initializing
|
92
|
+
if @mode == :offline
|
93
|
+
@state = :running
|
94
|
+
else
|
95
|
+
@state = :flushing
|
96
|
+
flush
|
97
|
+
end
|
98
|
+
@mode = :online if @mode == :initializing
|
99
|
+
end
|
100
|
+
true
|
101
|
+
end
|
102
|
+
|
103
|
+
# Is agent currently offline?
|
104
|
+
#
|
105
|
+
# === Return
|
106
|
+
# (Boolean):: true if agent offline, otherwise false
|
107
|
+
def offline?
|
108
|
+
@mode == :offline || @state == :created
|
109
|
+
end
|
110
|
+
|
111
|
+
# In request queueing mode?
|
112
|
+
#
|
113
|
+
# === Return
|
114
|
+
# (Boolean):: true if should queue request, otherwise false
|
115
|
+
def queueing?
|
116
|
+
offline? && @state != :flushing
|
117
|
+
end
|
118
|
+
|
119
|
+
# Switch to offline mode
|
120
|
+
# In this mode requests are queued in memory rather than being sent
|
121
|
+
# Idempotent
|
122
|
+
#
|
123
|
+
# === Return
|
124
|
+
# true:: Always return true
|
125
|
+
def enable
|
126
|
+
if offline?
|
127
|
+
if @state == :flushing
|
128
|
+
# If we were in offline mode then switched back to online but are still in the
|
129
|
+
# process of flushing the in-memory queue and are now switching to offline mode
|
130
|
+
# again then stop the flushing
|
131
|
+
@state = :running
|
132
|
+
end
|
133
|
+
else
|
134
|
+
Log.info("[offline] Disconnect from RightNet detected, entering offline mode")
|
135
|
+
Log.info("[offline] Messages will be queued in memory until RightNet connection is re-established")
|
136
|
+
@offline_stats.update
|
137
|
+
@queue ||= [] # Ensure queue is valid without losing any messages when going offline
|
138
|
+
@mode = :offline
|
139
|
+
start_timer
|
140
|
+
end
|
141
|
+
true
|
142
|
+
end
|
143
|
+
|
144
|
+
# Switch back to sending requests after in-memory queue gets flushed
|
145
|
+
# Idempotent
|
146
|
+
#
|
147
|
+
# === Return
|
148
|
+
# true:: Always return true
|
149
|
+
def disable
|
150
|
+
if offline? && @state != :created
|
151
|
+
Log.info("[offline] Connection to RightNet re-established")
|
152
|
+
@offline_stats.finish
|
153
|
+
cancel_timer
|
154
|
+
@state = :flushing
|
155
|
+
# Wait a bit to avoid flooding RightNet
|
156
|
+
EM.add_timer(rand(MAX_QUEUE_FLUSH_DELAY)) { flush }
|
157
|
+
end
|
158
|
+
true
|
159
|
+
end
|
160
|
+
|
161
|
+
# Queue given request in memory
|
162
|
+
#
|
163
|
+
# === Parameters
|
164
|
+
# request(Hash):: Request to be stored
|
165
|
+
#
|
166
|
+
# === Return
|
167
|
+
# true:: Always return true
|
168
|
+
def queue_request(kind, type, payload, target, callback)
|
169
|
+
request = {:kind => kind, :type => type, :payload => payload, :target => target, :callback => callback}
|
170
|
+
Log.info("[offline] Queuing request: #{request.inspect}")
|
171
|
+
vote_to_restart if (@restart_vote_count += 1) >= MAX_QUEUED_REQUESTS
|
172
|
+
if @state == :initializing
|
173
|
+
# We are in the initialization callback, requests should be put at the head of the queue
|
174
|
+
@queue.unshift(request)
|
175
|
+
else
|
176
|
+
@queue << request
|
177
|
+
end
|
178
|
+
true
|
179
|
+
end
|
180
|
+
|
181
|
+
# Prepare for agent termination
|
182
|
+
#
|
183
|
+
# === Return
|
184
|
+
# true:: Always return true
|
185
|
+
def terminate
|
186
|
+
@state = :terminating
|
187
|
+
cancel_timer
|
188
|
+
true
|
189
|
+
end
|
190
|
+
|
191
|
+
protected
|
192
|
+
|
193
|
+
# Send any requests that were queued while in offline mode
|
194
|
+
# Do this asynchronously to allow for agents to respond to requests
|
195
|
+
# Once all in-memory requests have been flushed, switch off offline mode
|
196
|
+
#
|
197
|
+
# === Parameters
|
198
|
+
# again(Boolean):: Whether being called in a loop
|
199
|
+
#
|
200
|
+
# === Return
|
201
|
+
# true:: Always return true
|
202
|
+
def flush(again = false)
|
203
|
+
if @state == :flushing
|
204
|
+
Log.info("[offline] Starting to flush request queue of size #{@queue.size}") unless again || @mode == :initializing
|
205
|
+
if @queue.any?
|
206
|
+
r = @queue.shift
|
207
|
+
if r[:callback]
|
208
|
+
Sender.instance.send(r[:kind], r[:type], r[:payload], r[:target]) { |result| r[:callback].call(result) }
|
209
|
+
else
|
210
|
+
Sender.instance.send(r[:kind], r[:type], r[:payload], r[:target])
|
211
|
+
end
|
212
|
+
end
|
213
|
+
if @queue.empty?
|
214
|
+
Log.info("[offline] Request queue flushed, resuming normal operations") unless @mode == :initializing
|
215
|
+
@mode = :online
|
216
|
+
@state = :running
|
217
|
+
else
|
218
|
+
EM.next_tick { flush(true) }
|
219
|
+
end
|
220
|
+
end
|
221
|
+
true
|
222
|
+
end
|
223
|
+
|
224
|
+
# Vote for restart and reset trigger
|
225
|
+
#
|
226
|
+
# === Parameters
|
227
|
+
# timer_trigger(Boolean):: true if vote was triggered by timer, false if it
|
228
|
+
# was triggered by number of messages in in-memory queue
|
229
|
+
#
|
230
|
+
# === Return
|
231
|
+
# true:: Always return true
|
232
|
+
def vote_to_restart(timer_trigger = false)
|
233
|
+
if @restart_vote
|
234
|
+
@restart_vote.call
|
235
|
+
if timer_trigger
|
236
|
+
start_timer
|
237
|
+
else
|
238
|
+
@restart_vote_count = 0
|
239
|
+
end
|
240
|
+
end
|
241
|
+
true
|
242
|
+
end
|
243
|
+
|
244
|
+
# Start restart vote timer
|
245
|
+
#
|
246
|
+
# === Return
|
247
|
+
# true:: Always return true
|
248
|
+
def start_timer
|
249
|
+
if @restart_vote && @state != :terminating
|
250
|
+
@restart_vote_timer ||= EM::Timer.new(RESTART_VOTE_DELAY) { vote_to_restart(timer_trigger = true) }
|
251
|
+
end
|
252
|
+
true
|
253
|
+
end
|
254
|
+
|
255
|
+
# Cancel restart vote timer
|
256
|
+
#
|
257
|
+
# === Return
|
258
|
+
# true:: Always return true
|
259
|
+
def cancel_timer
|
260
|
+
if @restart_vote_timer
|
261
|
+
@restart_vote_timer.cancel
|
262
|
+
@restart_vote_timer = nil
|
263
|
+
@restart_vote_count = 0
|
264
|
+
end
|
265
|
+
true
|
266
|
+
end
|
267
|
+
|
268
|
+
end # OfflineHandler
|
269
|
+
|
270
|
+
end # RightScale
|