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,247 @@
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
+ require 'thread'
24
+
25
+ module RightScale
26
+
27
+ # Provides access to core agents audit operation through helper methods
28
+ # that take care of formatting the audits appropriately
29
+ # Audit requests to audit recipes output are buffered as follows:
30
+ # * Start a timer after each call to audit output
31
+ # * Reset the timer if a new call to audit output is made
32
+ # * Actually send the output audit if the total size exceeds
33
+ # MAX_AUDIT_SIZE or the timer reaches MAX_AUDIT_DELAY
34
+ # * Audit of any other kind triggers a request and flushes the buffer
35
+ class AuditProxy
36
+
37
+ # Maximum size for accumulated output before sending audit request
38
+ # in characters
39
+ MAX_AUDIT_SIZE = 5 * 1024 # 5 KB
40
+
41
+ # Maximum amount of time to wait before sending audit request
42
+ # in seconds
43
+ MAX_AUDIT_DELAY = 2
44
+
45
+ # (Fixnum) Underlying audit id
46
+ attr_reader :audit_id
47
+
48
+ # Initialize audit from pre-existing id
49
+ #
50
+ # === Parameters
51
+ # audit_id(Fixnum):: Associated audit id
52
+ def initialize(audit_id)
53
+ @audit_id = audit_id
54
+ @size = 0
55
+ @buffer = ''
56
+ @mutex = Mutex.new
57
+ end
58
+
59
+ # Create a new audit and calls given block back asynchronously with it
60
+ #
61
+ # === Parameters
62
+ # agent_identity(AgentIdentity):: Agent identity used by core agent to retrieve corresponding account
63
+ # summary(String):: Summary to be used for newly created audit
64
+ #
65
+ # === Return
66
+ # true:: Always return true
67
+ def self.create(agent_identity, summary)
68
+ payload = {:agent_identity => agent_identity,
69
+ :summary => summary,
70
+ :category => RightScale::EventCategories::NONE}
71
+ Sender.instance.send_persistent_request("/auditor/create_entry", payload) do |r|
72
+ res = RightScale::OperationResult.from_results(r)
73
+ if res.success?
74
+ audit = new(res.content)
75
+ yield audit
76
+ else
77
+ Log.warning("Failed to create new audit entry with summary '#{summary}': #{res.content}, aborting...")
78
+ end
79
+ true
80
+ end
81
+ end
82
+
83
+ # Update audit summary
84
+ #
85
+ # === Parameters
86
+ # status(String):: New audit entry status
87
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
88
+ #
89
+ # === Return
90
+ # true:: Always return true
91
+ def update_status(status, options={})
92
+ send_audit(:kind => :status, :text => status, :category => options[:category])
93
+ end
94
+
95
+ # Start new audit section
96
+ #
97
+ # === Parameters
98
+ # title(String):: Title of new audit section, will replace audit status as well
99
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
100
+ #
101
+ # === Return
102
+ # true:: Always return true
103
+ def create_new_section(title, options={})
104
+ send_audit(:kind => :new_section, :text => title, :category => options[:category])
105
+ end
106
+
107
+ # Append info text to current audit section. A special marker will be prepended to each line of audit to
108
+ # indicate that text is not some output. Text will be line-wrapped.
109
+ #
110
+ # === Parameters
111
+ # text(String):: Informational text to append to audit entry
112
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
113
+ #
114
+ # === Return
115
+ # true:: Always return true
116
+ def append_info(text, options={})
117
+ send_audit(:kind => :info, :text => text, :category => options[:category])
118
+ end
119
+
120
+ # Append error message to current audit section. A special marker will be prepended to each line of audit to
121
+ # indicate that error message is not some output. Message will be line-wrapped.
122
+ #
123
+ # === Parameters
124
+ # text(String):: Error text to append to audit entry
125
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
126
+ #
127
+ # === Return
128
+ # true:: Always return true
129
+ def append_error(text, options={})
130
+ send_audit(:kind => :error, :text => text, :category => options[:category])
131
+ end
132
+
133
+ # Append output to current audit section
134
+ #
135
+ # === Parameters
136
+ # text(String):: Output to append to audit entry
137
+ #
138
+ # === Return
139
+ # true:: Always return true
140
+ #
141
+ # === Raise
142
+ # ApplicationError:: If audit id is missing from passed-in options
143
+ def append_output(text)
144
+ @mutex.synchronize do
145
+ @buffer << text
146
+ end
147
+
148
+ EM.next_tick do
149
+ buffer_size = nil
150
+ @mutex.synchronize do
151
+ buffer_size = @buffer.size
152
+ end
153
+
154
+ if buffer_size > MAX_AUDIT_SIZE
155
+ flush_buffer
156
+ else
157
+ reset_timer
158
+ end
159
+ end
160
+ end
161
+
162
+
163
+ protected
164
+
165
+ # Flush output buffer then send audits to core agent and log failures
166
+ #
167
+ # === Parameters
168
+ # options[:kind](Symbol):: One of :update_status, :new_section, :append_info, :append_error, :output
169
+ # options[:text](String):: Text to be audited
170
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
171
+ #
172
+ # === Return
173
+ # true:: Always return true
174
+ def send_audit(options)
175
+ flush_buffer
176
+ internal_send_audit(options)
177
+ end
178
+
179
+ # Actually send audits to core agent and log failures
180
+ #
181
+ # === Parameters
182
+ # options[:kind](Symbol):: One of :status, :new_section, :info, :error, :output
183
+ # options[:text](String):: Text to be audited
184
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
185
+ #
186
+ # === Return
187
+ # true:: Always return true
188
+ def internal_send_audit(options)
189
+ opts = { :audit_id => @audit_id, :category => options[:category], :offset => @size }
190
+ opts[:category] ||= EventCategories::CATEGORY_NOTIFICATION
191
+ unless EventCategories::CATEGORIES.include?(opts[:category])
192
+ Log.warning("Invalid category '#{opts[:category]}' for notification '#{options[:text]}', using generic category instead")
193
+ opts[:category] = EventCategories::CATEGORY_NOTIFICATION
194
+ end
195
+
196
+ log_method = options[:kind] == :error ? :error : :info
197
+ log_text = AuditFormatter.send(options[:kind], options[:text])[:detail]
198
+ log_text.chomp.split("\n").each { |l| Log.__send__(log_method, l) }
199
+ begin
200
+ audit = AuditFormatter.__send__(options[:kind], options[:text])
201
+ @size += audit[:detail].size
202
+ Sender.instance.send_persistent_push("/auditor/update_entry", opts.merge(audit))
203
+ rescue Exception => e
204
+ Log.warning("Failed to send audit", e, :trace)
205
+ end
206
+
207
+ true
208
+ end
209
+
210
+ # Send any buffered output to auditor
211
+ #
212
+ # === Return
213
+ # Always return true
214
+ def flush_buffer
215
+ # note we must discard cancelled timer or else we never create a new timer and stay cancelled.
216
+ if @timer
217
+ @timer.cancel
218
+ @timer = nil
219
+ end
220
+
221
+ to_send = nil
222
+ @mutex.synchronize do
223
+ unless @buffer.empty?
224
+ to_send = @buffer
225
+ @buffer = ''
226
+ end
227
+ end
228
+
229
+ if to_send
230
+ internal_send_audit(:kind => :output, :text => to_send, :category => EventCategories::NONE)
231
+ end
232
+ end
233
+
234
+ # Set or reset timer for buffer flush
235
+ #
236
+ # === Return
237
+ # true:: Always return true
238
+ def reset_timer
239
+ # note we are using a single PeriodicTimer because we were running out of
240
+ # one-shot timers with verbose script output. calling cancel on a one-shot
241
+ # timer sends a message but does not immediately remove the timer from EM
242
+ # which maxes out at 1000 one-shot timers.
243
+ @timer = EventMachine::PeriodicTimer.new(MAX_AUDIT_DELAY) { flush_buffer } unless @timer
244
+ end
245
+
246
+ end
247
+ end
@@ -0,0 +1,104 @@
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
+ # Abstract base class for a Bundle Queue.
26
+ class BundleQueue
27
+
28
+ FINAL_BUNDLE = 'end'
29
+ SHUTDOWN_BUNDLE = 'shutdown'
30
+
31
+ # Set continuation block to be called after 'close' is called
32
+ #
33
+ # === Block
34
+ # continuation block
35
+ def initialize(&continuation)
36
+ @continuation = continuation
37
+ end
38
+
39
+ # Determines if queue is active
40
+ #
41
+ # === Return
42
+ # active(Boolean):: true if queue is active
43
+ def active?
44
+ raise NotImplementedError.new("must be overridden")
45
+ end
46
+
47
+ # Activate queue for execution, idempotent
48
+ # Any pending bundle will be run sequentially in order
49
+ #
50
+ # === Return
51
+ # true:: Always return true
52
+ def activate
53
+ raise NotImplementedError.new("must be overridden")
54
+ end
55
+
56
+ # Determines if queue is busy
57
+ #
58
+ # === Return
59
+ # active(Boolean):: true if queue is busy
60
+ def busy?
61
+ raise NotImplementedError.new("must be overridden")
62
+ end
63
+
64
+ # Push new context to bundle queue and run next bundle
65
+ #
66
+ # === Parameters
67
+ # context(Object):: any supported kind of context
68
+ #
69
+ # === Return
70
+ # true:: Always return true
71
+ def push(context)
72
+ raise NotImplementedError.new("must be overridden")
73
+ end
74
+
75
+ # Clear queue content
76
+ #
77
+ # === Return
78
+ # true:: Always return true
79
+ def clear
80
+ raise NotImplementedError.new("must be overridden")
81
+ end
82
+
83
+ # Close queue so that further call to 'push' will be ignored
84
+ #
85
+ # === Return
86
+ # true:: Always return true
87
+ def close
88
+ raise NotImplementedError.new("must be overridden")
89
+ end
90
+
91
+ protected
92
+
93
+ # Invokes continuation (off of the current thread which may be going away).
94
+ #
95
+ # === Return
96
+ # true:: Always return true
97
+ def run_continuation
98
+ EM.next_tick { @continuation.call } if @continuation
99
+ true
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,109 @@
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 'singleton'
24
+
25
+ module RightScale
26
+
27
+ # Class managing connection to agent
28
+ module AgentConnection
29
+
30
+ # Wait up to 20 seconds before forcing disconnection to agent
31
+ STOP_TIMEOUT = 20
32
+
33
+ # Set command client cookie and initialize responses parser
34
+ def initialize(cookie, thread_name, callback=nil)
35
+ @cookie = cookie
36
+ @thread_name = thread_name
37
+ @pending = 0
38
+ @parser = CommandParser.new do |data|
39
+ if callback
40
+ callback.call(data)
41
+ else
42
+ Log.warning("[cook] Unexpected command protocol response '#{data}'") unless data == 'OK'
43
+ end
44
+ @pending -= 1
45
+ on_stopped if @stopped_callback && @pending == 0
46
+ end
47
+ end
48
+
49
+ # Send command to running agent
50
+ #
51
+ # === Parameters
52
+ # options(Hash):: Hash of options and command name
53
+ # options[:name]:: Command name
54
+ # options[:...]:: Other command specific options, passed through to agent
55
+ #
56
+ # === Return
57
+ # true:: Always return true
58
+ def send_command(options)
59
+ return if @stopped_callback
60
+ @pending += 1
61
+ command = options.dup
62
+ command[:cookie] = @cookie
63
+ command[:thread_name] = @thread_name
64
+ send_data(CommandSerializer.dump(command))
65
+ true
66
+ end
67
+
68
+ # Handle agent response
69
+ #
70
+ # === Return
71
+ # true:: Always return true
72
+ def receive_data(data)
73
+ @parser.parse_chunk(data)
74
+ true
75
+ end
76
+
77
+ # Stop command client, wait for all pending commands to finish prior
78
+ # to calling given callback
79
+ #
80
+ # === Return
81
+ # true:: Always return true
82
+ #
83
+ # === Block
84
+ # called once all pending commands have completed
85
+ def stop(&callback)
86
+ send_command(:name => :close_connection)
87
+ @stopped_callback = callback
88
+ Log.info("[cook] Disconnecting from agent (#{@pending} response#{@pending > 1 ? 's' : ''} pending)")
89
+ @stop_timeout = EM::Timer.new(STOP_TIMEOUT) do
90
+ Log.warning("[cook] Time out waiting for responses from agent, forcing disconnection")
91
+ @stop_timeout = nil
92
+ on_stopped
93
+ end
94
+ true
95
+ end
96
+
97
+ # Called after all pending responses have been received
98
+ #
99
+ # === Return
100
+ # true:: Always return true
101
+ def on_stopped
102
+ close_connection
103
+ @stop_timeout.cancel if @stop_timeout
104
+ @stopped_callback.call
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,165 @@
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
+ require 'logger'
24
+
25
+ module RightScale
26
+
27
+ # Audit logger formatter
28
+ class AuditLogFormatter < ::Logger::Formatter
29
+
30
+ # Generate log line from given input
31
+ def call(severity, time, progname, msg)
32
+ sprintf("%s: %s\n", time.strftime("%H:%M:%S"), msg2str(msg))
33
+ end
34
+
35
+ end
36
+
37
+ # Provides logger interface but forwards some logging to audit entry.
38
+ # Used in combination with Chef to audit recipe execution output.
39
+ class AuditLogger < ::Logger
40
+
41
+ # Underlying audit id
42
+ attr_reader :audit_id
43
+
44
+ # Initialize audit logger, override Logger initialize since there is no need to initialize @logdev
45
+ #
46
+ # === Parameters
47
+ # audit_id(Integer):: Audit id used to audit logs
48
+ def initialize
49
+ @progname = nil
50
+ @level = INFO
51
+ @default_formatter = AuditLogFormatter.new
52
+ @formatter = nil
53
+ @logdev = nil
54
+ end
55
+
56
+ # Return level as a symbol
57
+ #
58
+ # === Return
59
+ # level(Symbol):: One of :debug, :info, :warn, :error or :fatal
60
+ alias :level_orig :level
61
+ def level
62
+ level = { Logger::DEBUG => :debug,
63
+ Logger::INFO => :info,
64
+ Logger::WARN => :warn,
65
+ Logger::ERROR => :error,
66
+ Logger::FATAL => :fatal }[level_orig]
67
+ end
68
+
69
+ # Raw output
70
+ #
71
+ # === Parameters
72
+ # msg(String):: Raw string to be appended to audit
73
+ def <<(msg)
74
+ AuditStub.instance.append_output(msg)
75
+ end
76
+
77
+ # Override Logger::add to audit instead of writing to log file
78
+ #
79
+ # === Parameters
80
+ # severity(Constant):: One of Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR or Logger::FATAL
81
+ # message(String):: Message to be audited
82
+ # progname(String):: Override default program name for that audit
83
+ #
84
+ # === Block
85
+ # Call given Block if any to build message if +message+ is nil
86
+ #
87
+ # === Return
88
+ # true:: Always return true
89
+ def add(severity, message=nil, progname=nil, &block)
90
+ severity ||= UNKNOWN
91
+ # We don't want to audit logs that are less than our level
92
+ return true if severity < @level
93
+ progname ||= @progname
94
+ if message.nil?
95
+ if block_given?
96
+ message = yield
97
+ else
98
+ message = progname
99
+ progname = @progname
100
+ end
101
+ end
102
+ return true if is_filtered?(severity, message)
103
+ msg = format_message(format_severity(severity), Time.now, progname, message)
104
+ case severity
105
+ when Logger::DEBUG
106
+ Log.debug(message)
107
+ when Logger::INFO, Logger::WARN, Logger::UNKNOWN
108
+ AuditStub.instance.append_output(msg)
109
+ when Logger::ERROR
110
+ AuditStub.instance.append_error(msg)
111
+ when Logger::FATAL
112
+ AuditStub.instance.append_error(msg, :category => RightScale::EventCategories::CATEGORY_ERROR)
113
+ end
114
+ true
115
+ end
116
+
117
+ # Start new audit section
118
+ # Note: This is a special 'log' method which allows us to create audit sections before
119
+ # running RightScripts
120
+ #
121
+ # === Parameters
122
+ # title(String):: Title of new audit section, will replace audit status as well
123
+ # options[:category](String):: Optional, must be one of RightScale::EventCategories::CATEGORIES
124
+ #
125
+ # === Return
126
+ # true:: Always return true
127
+ def create_new_section(title, options={})
128
+ AuditStub.instance.create_new_section(title, options)
129
+ end
130
+
131
+ protected
132
+
133
+ MESSAGE_FILTERS = {
134
+ Logger::ERROR => [
135
+ # Suppress the auditing of anything Chef logs with ERROR severity that
136
+ # concerns itself with the right_scripts_cookbook. This cookbook is
137
+ # dynamically generated by the instance and concerns itself with
138
+ # RightScripts, which have their own independent mechanism for auditing
139
+ # failures.
140
+ #
141
+ # There are two flavors of this suppression: one for Linux, one for Windows.
142
+ # This is because Windows-generated RightScript recipes have slightly different
143
+ # naming conventions than Linux-generated.
144
+ %r{\(right_scripts_cookbook::.+ line \d+\)},
145
+ %r{\(right_scripts_cookbook::.+\.ps1 line .+\.ps1\.rb\)}
146
+ ]
147
+ }
148
+
149
+ # Filters any message which should not appear in audits.
150
+ #
151
+ # === Parameters
152
+ # severity(Constant):: One of Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR or Logger::FATAL
153
+ # message(String):: Message to be audited
154
+ def is_filtered?(severity, message)
155
+ if filters = MESSAGE_FILTERS[severity]
156
+ filters.each do |filter|
157
+ return true if filter =~ message
158
+ end
159
+ end
160
+ return false
161
+ end
162
+
163
+ end
164
+
165
+ end