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,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