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.
Files changed (176) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +82 -0
  3. data/Rakefile +113 -0
  4. data/lib/right_agent.rb +59 -0
  5. data/lib/right_agent/actor.rb +182 -0
  6. data/lib/right_agent/actor_registry.rb +76 -0
  7. data/lib/right_agent/actors/agent_manager.rb +232 -0
  8. data/lib/right_agent/agent.rb +1149 -0
  9. data/lib/right_agent/agent_config.rb +480 -0
  10. data/lib/right_agent/agent_identity.rb +210 -0
  11. data/lib/right_agent/agent_tag_manager.rb +237 -0
  12. data/lib/right_agent/audit_formatter.rb +107 -0
  13. data/lib/right_agent/clients.rb +31 -0
  14. data/lib/right_agent/clients/api_client.rb +383 -0
  15. data/lib/right_agent/clients/auth_client.rb +247 -0
  16. data/lib/right_agent/clients/balanced_http_client.rb +369 -0
  17. data/lib/right_agent/clients/base_retry_client.rb +495 -0
  18. data/lib/right_agent/clients/right_http_client.rb +279 -0
  19. data/lib/right_agent/clients/router_client.rb +493 -0
  20. data/lib/right_agent/command.rb +30 -0
  21. data/lib/right_agent/command/agent_manager_commands.rb +150 -0
  22. data/lib/right_agent/command/command_client.rb +136 -0
  23. data/lib/right_agent/command/command_constants.rb +33 -0
  24. data/lib/right_agent/command/command_io.rb +126 -0
  25. data/lib/right_agent/command/command_parser.rb +87 -0
  26. data/lib/right_agent/command/command_runner.rb +118 -0
  27. data/lib/right_agent/command/command_serializer.rb +63 -0
  28. data/lib/right_agent/connectivity_checker.rb +179 -0
  29. data/lib/right_agent/console.rb +65 -0
  30. data/lib/right_agent/core_payload_types.rb +44 -0
  31. data/lib/right_agent/core_payload_types/cookbook.rb +61 -0
  32. data/lib/right_agent/core_payload_types/cookbook_position.rb +46 -0
  33. data/lib/right_agent/core_payload_types/cookbook_repository.rb +116 -0
  34. data/lib/right_agent/core_payload_types/cookbook_sequence.rb +70 -0
  35. data/lib/right_agent/core_payload_types/dev_repositories.rb +100 -0
  36. data/lib/right_agent/core_payload_types/dev_repository.rb +76 -0
  37. data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
  38. data/lib/right_agent/core_payload_types/executable_bundle.rb +130 -0
  39. data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
  40. data/lib/right_agent/core_payload_types/login_user.rb +79 -0
  41. data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
  42. data/lib/right_agent/core_payload_types/recipe_instantiation.rb +73 -0
  43. data/lib/right_agent/core_payload_types/repositories_bundle.rb +50 -0
  44. data/lib/right_agent/core_payload_types/right_script_attachment.rb +95 -0
  45. data/lib/right_agent/core_payload_types/right_script_instantiation.rb +94 -0
  46. data/lib/right_agent/core_payload_types/runlist_policy.rb +44 -0
  47. data/lib/right_agent/core_payload_types/secure_document.rb +66 -0
  48. data/lib/right_agent/core_payload_types/secure_document_location.rb +63 -0
  49. data/lib/right_agent/core_payload_types/software_repository_instantiation.rb +61 -0
  50. data/lib/right_agent/daemonize.rb +35 -0
  51. data/lib/right_agent/dispatched_cache.rb +109 -0
  52. data/lib/right_agent/dispatcher.rb +272 -0
  53. data/lib/right_agent/enrollment_result.rb +221 -0
  54. data/lib/right_agent/exceptions.rb +87 -0
  55. data/lib/right_agent/history.rb +145 -0
  56. data/lib/right_agent/log.rb +460 -0
  57. data/lib/right_agent/minimal.rb +46 -0
  58. data/lib/right_agent/monkey_patches.rb +30 -0
  59. data/lib/right_agent/monkey_patches/ruby_patch.rb +55 -0
  60. data/lib/right_agent/monkey_patches/ruby_patch/array_patch.rb +29 -0
  61. data/lib/right_agent/monkey_patches/ruby_patch/darwin_patch.rb +24 -0
  62. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch.rb +24 -0
  63. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +30 -0
  64. data/lib/right_agent/monkey_patches/ruby_patch/object_patch.rb +49 -0
  65. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch.rb +32 -0
  66. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +60 -0
  67. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/process_patch.rb +63 -0
  68. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/stdio_patch.rb +27 -0
  69. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/time_patch.rb +55 -0
  70. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/win32ole_patch.rb +34 -0
  71. data/lib/right_agent/multiplexer.rb +102 -0
  72. data/lib/right_agent/offline_handler.rb +270 -0
  73. data/lib/right_agent/operation_result.rb +300 -0
  74. data/lib/right_agent/packets.rb +673 -0
  75. data/lib/right_agent/payload_formatter.rb +104 -0
  76. data/lib/right_agent/pending_requests.rb +128 -0
  77. data/lib/right_agent/pid_file.rb +159 -0
  78. data/lib/right_agent/platform.rb +770 -0
  79. data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
  80. data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
  81. data/lib/right_agent/platform/unix/platform.rb +226 -0
  82. data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
  83. data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
  84. data/lib/right_agent/platform/windows/platform.rb +1808 -0
  85. data/lib/right_agent/protocol_version_mixin.rb +69 -0
  86. data/lib/right_agent/retryable_request.rb +195 -0
  87. data/lib/right_agent/scripts/agent_controller.rb +543 -0
  88. data/lib/right_agent/scripts/agent_deployer.rb +400 -0
  89. data/lib/right_agent/scripts/common_parser.rb +160 -0
  90. data/lib/right_agent/scripts/log_level_manager.rb +192 -0
  91. data/lib/right_agent/scripts/stats_manager.rb +268 -0
  92. data/lib/right_agent/scripts/usage.rb +58 -0
  93. data/lib/right_agent/secure_identity.rb +92 -0
  94. data/lib/right_agent/security.rb +32 -0
  95. data/lib/right_agent/security/cached_certificate_store_proxy.rb +77 -0
  96. data/lib/right_agent/security/certificate.rb +102 -0
  97. data/lib/right_agent/security/certificate_cache.rb +89 -0
  98. data/lib/right_agent/security/distinguished_name.rb +56 -0
  99. data/lib/right_agent/security/encrypted_document.rb +83 -0
  100. data/lib/right_agent/security/rsa_key_pair.rb +76 -0
  101. data/lib/right_agent/security/signature.rb +86 -0
  102. data/lib/right_agent/security/static_certificate_store.rb +85 -0
  103. data/lib/right_agent/sender.rb +792 -0
  104. data/lib/right_agent/serialize.rb +29 -0
  105. data/lib/right_agent/serialize/message_pack.rb +107 -0
  106. data/lib/right_agent/serialize/secure_serializer.rb +151 -0
  107. data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
  108. data/lib/right_agent/serialize/serializable.rb +151 -0
  109. data/lib/right_agent/serialize/serializer.rb +159 -0
  110. data/lib/right_agent/subprocess.rb +38 -0
  111. data/lib/right_agent/tracer.rb +124 -0
  112. data/right_agent.gemspec +101 -0
  113. data/spec/actor_registry_spec.rb +80 -0
  114. data/spec/actor_spec.rb +162 -0
  115. data/spec/agent_config_spec.rb +235 -0
  116. data/spec/agent_identity_spec.rb +78 -0
  117. data/spec/agent_spec.rb +734 -0
  118. data/spec/agent_tag_manager_spec.rb +319 -0
  119. data/spec/clients/api_client_spec.rb +423 -0
  120. data/spec/clients/auth_client_spec.rb +272 -0
  121. data/spec/clients/balanced_http_client_spec.rb +576 -0
  122. data/spec/clients/base_retry_client_spec.rb +635 -0
  123. data/spec/clients/router_client_spec.rb +594 -0
  124. data/spec/clients/spec_helper.rb +111 -0
  125. data/spec/command/agent_manager_commands_spec.rb +51 -0
  126. data/spec/command/command_io_spec.rb +93 -0
  127. data/spec/command/command_parser_spec.rb +79 -0
  128. data/spec/command/command_runner_spec.rb +107 -0
  129. data/spec/command/command_serializer_spec.rb +51 -0
  130. data/spec/connectivity_checker_spec.rb +83 -0
  131. data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
  132. data/spec/core_payload_types/dev_repository_spec.rb +33 -0
  133. data/spec/core_payload_types/executable_bundle_spec.rb +67 -0
  134. data/spec/core_payload_types/login_user_spec.rb +102 -0
  135. data/spec/core_payload_types/recipe_instantiation_spec.rb +81 -0
  136. data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
  137. data/spec/core_payload_types/right_script_instantiation_spec.rb +79 -0
  138. data/spec/core_payload_types/spec_helper.rb +23 -0
  139. data/spec/dispatched_cache_spec.rb +136 -0
  140. data/spec/dispatcher_spec.rb +324 -0
  141. data/spec/enrollment_result_spec.rb +53 -0
  142. data/spec/history_spec.rb +246 -0
  143. data/spec/log_spec.rb +192 -0
  144. data/spec/monkey_patches/eventmachine_spec.rb +62 -0
  145. data/spec/multiplexer_spec.rb +48 -0
  146. data/spec/offline_handler_spec.rb +340 -0
  147. data/spec/operation_result_spec.rb +208 -0
  148. data/spec/packets_spec.rb +461 -0
  149. data/spec/pending_requests_spec.rb +136 -0
  150. data/spec/platform/spec_helper.rb +216 -0
  151. data/spec/platform/unix/darwin/platform_spec.rb +181 -0
  152. data/spec/platform/unix/linux/platform_spec.rb +540 -0
  153. data/spec/platform/unix/spec_helper.rb +149 -0
  154. data/spec/platform/windows/mingw/platform_spec.rb +222 -0
  155. data/spec/platform/windows/mswin/platform_spec.rb +259 -0
  156. data/spec/platform/windows/spec_helper.rb +720 -0
  157. data/spec/retryable_request_spec.rb +306 -0
  158. data/spec/secure_identity_spec.rb +50 -0
  159. data/spec/security/cached_certificate_store_proxy_spec.rb +62 -0
  160. data/spec/security/certificate_cache_spec.rb +71 -0
  161. data/spec/security/certificate_spec.rb +49 -0
  162. data/spec/security/distinguished_name_spec.rb +46 -0
  163. data/spec/security/encrypted_document_spec.rb +55 -0
  164. data/spec/security/rsa_key_pair_spec.rb +55 -0
  165. data/spec/security/signature_spec.rb +66 -0
  166. data/spec/security/static_certificate_store_spec.rb +58 -0
  167. data/spec/sender_spec.rb +1045 -0
  168. data/spec/serialize/message_pack_spec.rb +131 -0
  169. data/spec/serialize/secure_serializer_spec.rb +132 -0
  170. data/spec/serialize/serializable_spec.rb +90 -0
  171. data/spec/serialize/serializer_spec.rb +197 -0
  172. data/spec/spec.opts +2 -0
  173. data/spec/spec.win32.opts +1 -0
  174. data/spec/spec_helper.rb +130 -0
  175. data/spec/tracer_spec.rb +114 -0
  176. 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