right_link 5.9.0

Sign up to get free protection for your applications and to get access to all the features.
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