right_link 5.9.0

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 (199) hide show
  1. data/actors/agent_manager.rb +88 -0
  2. data/actors/instance_scheduler.rb +321 -0
  3. data/actors/instance_services.rb +64 -0
  4. data/actors/instance_setup.rb +567 -0
  5. data/bin/cloud +25 -0
  6. data/bin/cook_runner +44 -0
  7. data/bin/deploy +120 -0
  8. data/bin/enroll +385 -0
  9. data/bin/rad +32 -0
  10. data/bin/rchk +29 -0
  11. data/bin/rnac +39 -0
  12. data/bin/rs_connect +33 -0
  13. data/bin/rs_log_level +31 -0
  14. data/bin/rs_ohai +28 -0
  15. data/bin/rs_reenroll +31 -0
  16. data/bin/rs_run_recipe +34 -0
  17. data/bin/rs_run_right_script +34 -0
  18. data/bin/rs_shutdown +33 -0
  19. data/bin/rs_tag +33 -0
  20. data/bin/rs_thunk +33 -0
  21. data/bin/rstat +31 -0
  22. data/bin/system +16 -0
  23. data/ext/Rakefile +18 -0
  24. data/init/config.yml +5 -0
  25. data/init/init.rb +79 -0
  26. data/lib/chef/ohai_setup.rb +51 -0
  27. data/lib/chef/plugins/cloud.rb +91 -0
  28. data/lib/chef/plugins/cloudstack.rb +23 -0
  29. data/lib/chef/plugins/ec2.rb +23 -0
  30. data/lib/chef/plugins/linux/block_device2.rb +24 -0
  31. data/lib/chef/plugins/rackspace.rb +23 -0
  32. data/lib/chef/plugins/rightscale.rb +125 -0
  33. data/lib/chef/plugins/windows/network.rb +114 -0
  34. data/lib/chef/plugins.rb +74 -0
  35. data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
  36. data/lib/chef/providers/dns_resource.rb +100 -0
  37. data/lib/chef/providers/executable_schedule_provider.rb +70 -0
  38. data/lib/chef/providers/executable_schedule_resource.rb +144 -0
  39. data/lib/chef/providers/remote_recipe_provider.rb +86 -0
  40. data/lib/chef/providers/remote_recipe_resource.rb +101 -0
  41. data/lib/chef/providers/right_link_tag_provider.rb +73 -0
  42. data/lib/chef/providers/right_link_tag_resource.rb +59 -0
  43. data/lib/chef/providers/right_script_provider.rb +190 -0
  44. data/lib/chef/providers/right_script_resource.rb +113 -0
  45. data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
  46. data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
  47. data/lib/chef/providers/server_collection_provider.rb +66 -0
  48. data/lib/chef/providers/server_collection_resource.rb +93 -0
  49. data/lib/chef/providers/windows/powershell_provider.rb +151 -0
  50. data/lib/chef/providers/windows/powershell_resource.rb +111 -0
  51. data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
  52. data/lib/chef/right_providers.rb +55 -0
  53. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
  54. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
  55. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
  56. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
  57. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
  58. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
  59. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
  60. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
  61. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
  62. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
  63. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
  64. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
  65. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
  66. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
  67. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
  68. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
  69. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
  70. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
  71. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
  72. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
  73. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
  74. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  75. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
  76. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
  77. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
  78. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
  79. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
  80. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
  81. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
  82. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
  83. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
  84. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
  85. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
  86. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
  87. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
  88. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
  89. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
  90. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
  91. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
  92. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
  93. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  94. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
  95. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
  96. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
  97. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
  98. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
  99. data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
  100. data/lib/chef/windows/chef_node_server.rb +463 -0
  101. data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
  102. data/lib/chef/windows/pipe_server.rb +283 -0
  103. data/lib/chef/windows/powershell_host.rb +285 -0
  104. data/lib/chef/windows/powershell_pipe_server.rb +136 -0
  105. data/lib/chef/windows/powershell_provider_base.rb +92 -0
  106. data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
  107. data/lib/clouds/cloud.rb +557 -0
  108. data/lib/clouds/cloud_factory.rb +250 -0
  109. data/lib/clouds/cloud_utilities.rb +244 -0
  110. data/lib/clouds/clouds/azure.rb +106 -0
  111. data/lib/clouds/clouds/cloudstack.rb +114 -0
  112. data/lib/clouds/clouds/ec2.rb +113 -0
  113. data/lib/clouds/clouds/eucalyptus.rb +46 -0
  114. data/lib/clouds/clouds/google.rb +102 -0
  115. data/lib/clouds/clouds/none.rb +76 -0
  116. data/lib/clouds/clouds/openstack.rb +30 -0
  117. data/lib/clouds/clouds/rackspace-ng.rb +54 -0
  118. data/lib/clouds/clouds/rackspace.rb +78 -0
  119. data/lib/clouds/clouds/softlayer.rb +91 -0
  120. data/lib/clouds/metadata_formatter.rb +108 -0
  121. data/lib/clouds/metadata_provider.rb +128 -0
  122. data/lib/clouds/metadata_source.rb +87 -0
  123. data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
  124. data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
  125. data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
  126. data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
  127. data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
  128. data/lib/clouds/metadata_tree_climber.rb +144 -0
  129. data/lib/clouds/metadata_writer.rb +155 -0
  130. data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
  131. data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
  132. data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
  133. data/lib/clouds/register_clouds.rb +34 -0
  134. data/lib/clouds.rb +32 -0
  135. data/lib/gem_dependencies.rb +83 -0
  136. data/lib/git_hooks/commit-msg.rb +7 -0
  137. data/lib/instance/agent_config.rb +168 -0
  138. data/lib/instance/agent_watcher.rb +233 -0
  139. data/lib/instance/audit_cook_stub.rb +104 -0
  140. data/lib/instance/audit_proxy.rb +247 -0
  141. data/lib/instance/bundle_queue.rb +104 -0
  142. data/lib/instance/cook/agent_connection.rb +109 -0
  143. data/lib/instance/cook/audit_logger.rb +165 -0
  144. data/lib/instance/cook/audit_stub.rb +142 -0
  145. data/lib/instance/cook/ca-bundle.crt +2794 -0
  146. data/lib/instance/cook/chef_state.rb +211 -0
  147. data/lib/instance/cook/cook.rb +306 -0
  148. data/lib/instance/cook/cook_state.rb +298 -0
  149. data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
  150. data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
  151. data/lib/instance/cook/executable_sequence.rb +765 -0
  152. data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
  153. data/lib/instance/cook/repose_downloader.rb +349 -0
  154. data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
  155. data/lib/instance/cook.rb +41 -0
  156. data/lib/instance/downloader.rb +208 -0
  157. data/lib/instance/duplicable.rb +67 -0
  158. data/lib/instance/exceptions.rb +49 -0
  159. data/lib/instance/executable_sequence_proxy.rb +278 -0
  160. data/lib/instance/instance_commands.rb +577 -0
  161. data/lib/instance/instance_state.rb +633 -0
  162. data/lib/instance/json_utilities.rb +102 -0
  163. data/lib/instance/login_manager.rb +533 -0
  164. data/lib/instance/login_user_manager.rb +522 -0
  165. data/lib/instance/message_encoder.rb +118 -0
  166. data/lib/instance/multi_thread_bundle_queue.rb +232 -0
  167. data/lib/instance/operation_context.rb +60 -0
  168. data/lib/instance/options_bag.rb +65 -0
  169. data/lib/instance/payload_formatter.rb +46 -0
  170. data/lib/instance/policy.rb +53 -0
  171. data/lib/instance/policy_audit.rb +100 -0
  172. data/lib/instance/policy_manager.rb +146 -0
  173. data/lib/instance/reenroll_manager.rb +104 -0
  174. data/lib/instance/right_scripts_cookbook.rb +181 -0
  175. data/lib/instance/shutdown_request.rb +221 -0
  176. data/lib/instance/single_thread_bundle_queue.rb +189 -0
  177. data/lib/instance/volume_management.rb +450 -0
  178. data/lib/instance.rb +50 -0
  179. data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
  180. data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
  181. data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
  182. data/lib/repo_conf_generators/rightscale_key.pub +17 -0
  183. data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
  184. data/lib/repo_conf_generators.rb +30 -0
  185. data/lib/run_shell.rb +28 -0
  186. data/scripts/agent_checker.rb +571 -0
  187. data/scripts/agent_controller.rb +247 -0
  188. data/scripts/agent_deployer.rb +148 -0
  189. data/scripts/bundle_runner.rb +336 -0
  190. data/scripts/cloud_controller.rb +176 -0
  191. data/scripts/log_level_manager.rb +142 -0
  192. data/scripts/ohai_runner.rb +33 -0
  193. data/scripts/reenroller.rb +193 -0
  194. data/scripts/server_importer.rb +293 -0
  195. data/scripts/shutdown_client.rb +183 -0
  196. data/scripts/system_configurator.rb +367 -0
  197. data/scripts/tagger.rb +381 -0
  198. data/scripts/thunker.rb +356 -0
  199. metadata +418 -0
@@ -0,0 +1,232 @@
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
+ module RightScale
24
+
25
+ class MultiThreadBundleQueue < BundleQueue
26
+
27
+ THREAD_QUEUE_CLOSED_BUNDLE = 'thread queue closed'
28
+
29
+ # Set continuation block to be called after 'close' is called
30
+ #
31
+ # === Block
32
+ # continuation block
33
+ def initialize(&continuation)
34
+ super(&continuation)
35
+ @active = false
36
+ @thread = nil
37
+ @mutex = Mutex.new
38
+ @queue = Queue.new
39
+ @thread_name_to_queue = {}
40
+ end
41
+
42
+ # Determines if queue is active
43
+ #
44
+ # === Return
45
+ # active(Boolean):: true if queue is active
46
+ def active?
47
+ active = false
48
+ @mutex.synchronize { active = @active }
49
+ return active
50
+ end
51
+
52
+ # Activate queue for execution, idempotent
53
+ # Any pending bundle will be run sequentially in order
54
+ #
55
+ # === Return
56
+ # true:: Always return true
57
+ def activate
58
+ @mutex.synchronize do
59
+ unless @active
60
+ @thread = Thread.new { run }
61
+ @active = true
62
+ end
63
+ end
64
+ true
65
+ end
66
+
67
+ # Determines if queue is busy
68
+ #
69
+ # === Return
70
+ # active(Boolean):: true if queue is busy
71
+ def busy?
72
+ busy = false
73
+ @mutex.synchronize { busy = @thread_name_to_queue.any? { |_, q| q.busy? } }
74
+ busy
75
+ end
76
+
77
+ # Push new context to bundle queue and run next bundle
78
+ #
79
+ # === Return
80
+ # true:: Always return true
81
+ def push(context)
82
+ @queue << context
83
+ true
84
+ end
85
+
86
+ # Clear queue content
87
+ #
88
+ # === Return
89
+ # true:: Always return true
90
+ def clear
91
+ @queue.clear
92
+ @mutex.synchronize { @thread_name_to_queue.each_value { |queue| queue.clear } }
93
+ true
94
+ end
95
+
96
+ # Close queue so that further call to 'push' will be ignored
97
+ #
98
+ # === Return
99
+ # true:: Always return true
100
+ def close
101
+ push(FINAL_BUNDLE)
102
+ end
103
+
104
+ protected
105
+
106
+ # Run next bundle in the queue if active
107
+ # If bundle is FINAL_BUNDLE then call continuation block and deactivate
108
+ #
109
+ # === Return
110
+ # true:: Always return true
111
+ def run
112
+ close_requested = false
113
+ shutdown_requested = false
114
+ loop do
115
+ context = @queue.shift
116
+ if context == FINAL_BUNDLE
117
+ if close_thread_queues
118
+ close_requested = true
119
+ else
120
+ break
121
+ end
122
+ elsif context == THREAD_QUEUE_CLOSED_BUNDLE
123
+ unless groom_thread_queues
124
+ if shutdown_requested
125
+ # reset shutdown flag, push shutdown and wait for FINAL_BUNDLE
126
+ shutdown_requested = false
127
+ push_to_thread_queue(SHUTDOWN_BUNDLE)
128
+ else
129
+ break
130
+ end
131
+ end
132
+ elsif context == SHUTDOWN_BUNDLE
133
+ if close_thread_queues
134
+ # defer shutdown until all thread queues close (threads are
135
+ # uninterruptable but the user can always kick the plug out).
136
+ shutdown_requested = true
137
+ else
138
+ # push shutdown and wait for FINAL_BUNDLE
139
+ push_to_thread_queue(SHUTDOWN_BUNDLE)
140
+ end
141
+ elsif !context.decommission? && ShutdownRequest.instance.immediately?
142
+ # immediate shutdown pre-empts any futher attempts to run operational
143
+ # scripts but still allows the decommission bundle to run.
144
+ context.audit.update_status("Skipped bundle due to immediate shutdown: #{context.payload}")
145
+ # proceed ignoring bundles until final or shutdown are encountered.
146
+ else
147
+ push_to_thread_queue(context) unless close_requested
148
+ end
149
+ end
150
+ true
151
+ rescue Exception => e
152
+ Log.error(Log.format("MultiThreadBundleQueue.run failed", e, :trace))
153
+ ensure
154
+ # invoke continuation (off of this thread which is going away).
155
+ @mutex.synchronize { @active = false }
156
+ EM.next_tick { @continuation.call } if @continuation
157
+ @thread = nil
158
+ end
159
+
160
+ # Pushes a context to a thread based on a name determined from the context.
161
+ #
162
+ # === Parameters
163
+ # context(Object):: any kind of context object
164
+ #
165
+ # === Return
166
+ # true:: always true
167
+ def push_to_thread_queue(context)
168
+ thread_name = context.respond_to?(:thread_name) ? context.thread_name : ::RightScale::AgentConfig.default_thread_name
169
+ queue = nil
170
+ @mutex.synchronize do
171
+ queue = @thread_name_to_queue[thread_name]
172
+ unless queue
173
+ # continuation for when thread-named queue is finally closed.
174
+ queue = create_thread_queue(thread_name) { push(THREAD_QUEUE_CLOSED_BUNDLE) }
175
+ @thread_name_to_queue[thread_name] = queue
176
+ end
177
+ end
178
+
179
+ # push context to selected thread queue
180
+ queue.push(context)
181
+
182
+ # always (re)activate in case an individual thread queue died unexpectedly.
183
+ # has no effect if already active.
184
+ queue.activate
185
+ true
186
+ end
187
+
188
+ # Factory method for a thread-specific queue.
189
+ #
190
+ # === Parameters
191
+ # thread_name(String):: name of thread for queue being created
192
+ # continuation(Proc):: continuation run on thread termination
193
+ #
194
+ # === Return
195
+ # queue(BundleQueue):: a new thread-specific queue
196
+ def create_thread_queue(thread_name, &continuation)
197
+ return SingleThreadBundleQueue.new(thread_name, &continuation)
198
+ end
199
+
200
+ # Deletes any inactive queues from the hash of known queues.
201
+ #
202
+ # === Return
203
+ # still_active(Boolean):: true if any queues are still active
204
+ def groom_thread_queues
205
+ still_active = false
206
+ @mutex.synchronize do
207
+ @thread_name_to_queue.delete_if { |_, queue| false == queue.active? }
208
+ still_active = false == @thread_name_to_queue.empty?
209
+ end
210
+ return still_active
211
+ end
212
+
213
+ # Closes all thread queues.
214
+ #
215
+ # === Return
216
+ # result(Boolean):: true if any queues are still active (and stopping)
217
+ def close_thread_queues
218
+ still_active = false
219
+ @mutex.synchronize do
220
+ @thread_name_to_queue.each_value do |queue|
221
+ if queue.active?
222
+ queue.close
223
+ still_active = true
224
+ end
225
+ end
226
+ end
227
+ return still_active
228
+ end
229
+
230
+ end # MultiThreadBundleQueue
231
+
232
+ end # RightScale
@@ -0,0 +1,60 @@
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
+ # Context required to run an operation
26
+ # Includes operation input and associated audit
27
+ class OperationContext
28
+
29
+ # @return [Object] payload associated with operation
30
+ attr_reader :payload
31
+
32
+ # @return [RightScale::AuditProxy] audit for execution
33
+ attr_reader :audit
34
+
35
+ # @return [TrueClass|FalseClass] true if bundle succeeded
36
+ attr_accessor :succeeded
37
+
38
+ # @return [TrueClass|FalseClass] true if a decommission bundle
39
+ def decommission?; !!@decommission_type; end
40
+
41
+ # @return [String] decommission_type or nil
42
+ attr_reader :decommission_type
43
+
44
+ # @return [String] thread name for context or default thread name
45
+ attr_reader :thread_name
46
+
47
+ # @param [Object] payload of any kind (but usually executable bundle)
48
+ # @param [RightScale::AuditProxy] audit for execution
49
+ # @param [Hash] options for context
50
+ # @option options [String] :decommission_type for decommission bundle
51
+ def initialize(payload, audit, options={})
52
+ @payload = payload
53
+ @audit = audit
54
+ @decommission_type = options[:decommission_type]
55
+ @thread_name = payload.respond_to?(:runlist_policy) && payload.runlist_policy ? payload.runlist_policy.thread_name : ::RightScale::AgentConfig.default_thread_name
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,65 @@
1
+ #
2
+ # Copyright (c) 2010-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 'json'
24
+
25
+ module RightScale
26
+
27
+ # Store agent options in environment variable so child processes
28
+ # can access them too
29
+ class OptionsBag
30
+
31
+ # (String) Name of environment variable containing serialized options hash
32
+ OPTIONS_ENV = 'RS_OPTIONS'
33
+
34
+ # Store options
35
+ #
36
+ # === Parameters
37
+ # opts(Hash):: Options to be stored, override any options stored earlier
38
+ #
39
+ # === Result
40
+ # opts(Hash):: Options to be stored
41
+ def self.store(opts)
42
+ ENV[OPTIONS_ENV] = JSON.dump(opts)
43
+ opts
44
+ end
45
+
46
+ # Load previously stored options (may have been stored in a parent process)
47
+ #
48
+ # === Return
49
+ # opts(Hash):: Previously stored options, empty hash if there is none
50
+ def self.load
51
+ return {} unless serialized = ENV[OPTIONS_ENV]
52
+ begin
53
+ opts = JSON.load(serialized)
54
+ opts = SerializationHelper.symbolize_keys(opts)
55
+ rescue Exception => e
56
+ Log.warning("Failed to deserialize options", e)
57
+ opts = {}
58
+ end
59
+ opts
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
@@ -0,0 +1,46 @@
1
+ #
2
+ # Copyright (c) 2010-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
+ # Extend PayloadFormatter for instance agent payloads
26
+ class PayloadFormatter
27
+
28
+ protected
29
+
30
+ # state_recorder/record request log message
31
+ # Payload :
32
+ # { :agent_identity => ..., :state => ..., :user_id => ..., :skip_db_update => ..., :kind => ... }
33
+ #
34
+ # === Parameters
35
+ # payload(Hash):: Request payload
36
+ #
37
+ # === Return
38
+ # true:: Always return true
39
+ def state_recorder_record(payload)
40
+ msg = get(payload, :state)
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
@@ -0,0 +1,53 @@
1
+ #
2
+ # Copyright (c) 2009-2012 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module RightScale
24
+
25
+ class Policy
26
+ attr_accessor :policy_name, :audit_period, :audit, :count, :audit_timestamp
27
+
28
+ def initialize(policy_name, audit_period, audit)
29
+ @policy_name = policy_name.to_s
30
+ @audit_period = audit_period.to_i
31
+ @audit = RightScale::PolicyAudit.new(audit)
32
+ @count = 0
33
+ @audit_timestamp = Time.now
34
+
35
+ @audit.audit.append_info("First run of Reconvergence Policy '#{policy_name}' at #{Time.at(@audit_timestamp).to_s}")
36
+ end
37
+
38
+ def success
39
+ @count += 1
40
+ timestamp = Time.now
41
+ if timestamp - @audit_timestamp >= @audit_period
42
+ @audit.audit.append_info("Reconvergence Policy '#{@policy_name}' has run successfully #{@count} time#{@count > 1 ? 's' : ''} since #{Time.at(@audit_timestamp).to_s}")
43
+ @audit_timestamp = timestamp
44
+ @count = 0
45
+ end
46
+ end
47
+
48
+ def fail
49
+ @count = 0
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,100 @@
1
+ #
2
+ # Copyright (c) 2009-2012 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module RightScale
24
+
25
+ class PolicyAudit
26
+ # AuditProxy
27
+ attr_accessor :audit
28
+
29
+ # Creates a PolicyAudit to wrap AuditProxy
30
+ #
31
+ # === Parameters
32
+ # audit(AuditProxy):: the audit that pertains to the bundle
33
+ def initialize(audit)
34
+ @audit = audit
35
+ end
36
+
37
+ # # See AuditProxy::update_status
38
+ #
39
+ # === Parameters
40
+ # status(String):: New audit entry status
41
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
42
+ #
43
+ # === Return
44
+ # true:: Always return true
45
+ def update_status(status, options={})
46
+ true
47
+ end
48
+
49
+ # See AuditProxy::append_create_new_section
50
+ #
51
+ # === Parameters
52
+ # title(String):: Title of new audit section, will replace audit status as well
53
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
54
+ #
55
+ # === Return
56
+ # true:: Always return true
57
+ def create_new_section(title, options={})
58
+ RightScale::Log.info title
59
+ true
60
+ end
61
+
62
+ # See AuditProxy::append_info
63
+ #
64
+ # === Parameters
65
+ # text(String):: Informational text to append to audit entry
66
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
67
+ #
68
+ # === Return
69
+ # true:: Always return true
70
+ def append_info(text, options={})
71
+ true
72
+ end
73
+
74
+ # See AuditProxy::append_error
75
+ #
76
+ # === Parameters
77
+ # text(String):: Error text to append to audit entry
78
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
79
+ #
80
+ # === Return
81
+ # true:: Always return true
82
+ def append_error(text, options={})
83
+ @audit.append_error(text, options)
84
+ end
85
+
86
+ # See AuditProxy::append_output
87
+ #
88
+ # === Parameters
89
+ # text(String):: Output to append to audit entry
90
+ #
91
+ # === Return
92
+ # true:: Always return true
93
+ def append_output(text)
94
+ RightScale::Log.info text
95
+ true
96
+ end
97
+
98
+ end
99
+
100
+ end
@@ -0,0 +1,146 @@
1
+ #
2
+ # Copyright (c) 2009-2012 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
+ # Manages policies
26
+ class PolicyManager
27
+ # Policy hash keyed by policy name
28
+ @policies = Hash.new
29
+ @registrations = Hash.new
30
+
31
+ class << self
32
+ attr_reader :policy
33
+
34
+ def registered?(bundle)
35
+ @policies.has_key?(policy_name_from_bundle(bundle))
36
+ end
37
+
38
+ # Registers the bundle with the Manager and calls the passed in block when registration completes
39
+ # In a multithreaded environment, the
40
+ #
41
+ # === Parameters
42
+ # bundle(ExecutableBundle):: bundle containing a RunlistPolicy
43
+ # block(Block):: block to execute once registration is complete. The block will be called with
44
+ #
45
+ # === Return
46
+ # result(Boolean):: Return false if the bundle fails to provide a valid runlist policy
47
+ def register(bundle, &block)
48
+ runlist_policy = runlist_policy_from_bundle(bundle)
49
+ if runlist_policy
50
+ if registering?(runlist_policy.policy_name)
51
+ # waiting for a new audit to be created, place the block to be called on the list of callbacks
52
+ @registrations[runlist_policy.policy_name] << block if block
53
+ else
54
+ # this is the first registration, add the callback to the list of callbacks to be executed after the audit has been created
55
+ @registrations[runlist_policy.policy_name] = (block) ? [block] : []
56
+ # request a new audit
57
+ RightScale::AuditProxy.create(RightScale::InstanceState.identity, "Reconvergence Policy '#{runlist_policy.policy_name}'") do |audit|
58
+ policy = Policy.new(runlist_policy.policy_name, runlist_policy.audit_period, audit)
59
+ @policies[policy.policy_name] = policy
60
+ # drain the pending registrations
61
+ @registrations[policy.policy_name].each { |blk| blk.call(bundle, policy.audit) }
62
+ @registrations.delete(policy.policy_name)
63
+ end
64
+ end
65
+ true
66
+ end
67
+ false
68
+ end
69
+
70
+ # Signals the successful execution of a right script or recipe with the given bundle
71
+ #
72
+ # === Parameters
73
+ # bundle(ExecutableBundle):: bundle containing a RunlistPolicy
74
+ #
75
+ # === Return
76
+ # result(Boolean):: Return false if the bundle fails to provide a valid runlist policy
77
+ def success(bundle)
78
+ policy = get_policy_from_bundle(bundle)
79
+ return false unless policy
80
+ policy.success
81
+ true
82
+ end
83
+
84
+ # Signals the failed execution of a recipe with the given bundle
85
+ #
86
+ # === Parameters
87
+ # bundle(ExecutableBundle):: bundle containing a RunlistPolicy
88
+ #
89
+ # === Return
90
+ # result(Boolean):: Return false if the bundle fails to provide a valid runlist policy
91
+ def fail(bundle)
92
+ policy = get_policy_from_bundle(bundle)
93
+ return false unless policy
94
+ policy.fail
95
+ true
96
+ end
97
+
98
+ # Returns the audit for the given policy of the bundle
99
+ #
100
+ # === Parameters
101
+ # bundle(ExecutableBundle):: An executable bundle
102
+ #
103
+ # === Return
104
+ # result(PolicyAudit):: a PolicyAudit instance that wraps AuditProxy
105
+ def get_audit(bundle)
106
+ policy = get_policy_from_bundle(bundle)
107
+ policy ? policy.audit : nil
108
+ end
109
+
110
+ private
111
+
112
+ # Returns the policy that matches the bundle or creates a new one
113
+ #
114
+ # === Parameters
115
+ # bundle(ExecutableBundle):: An executable bundle
116
+ #
117
+ # === Return
118
+ # result(Policy):: Policy based on the bundle's RunlistPolicy or nil
119
+ def get_policy_from_bundle(bundle)
120
+ @policies[policy_name_from_bundle(bundle)]
121
+ end
122
+
123
+ def registering?(policy_name)
124
+ return @registrations.has_key?(policy_name)
125
+ end
126
+
127
+ def policy_name_from_bundle(bundle)
128
+ runlist_policy = runlist_policy_from_bundle(bundle)
129
+ if runlist_policy
130
+ return runlist_policy.policy_name
131
+ else
132
+ return nil
133
+ end
134
+ end
135
+
136
+ def runlist_policy_from_bundle(bundle)
137
+ if bundle.respond_to?(:runlist_policy) && bundle.runlist_policy && bundle.runlist_policy.policy_name
138
+ return bundle.runlist_policy
139
+ else
140
+ return nil
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ end