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.
- data/actors/agent_manager.rb +88 -0
- data/actors/instance_scheduler.rb +321 -0
- data/actors/instance_services.rb +64 -0
- data/actors/instance_setup.rb +567 -0
- data/bin/cloud +25 -0
- data/bin/cook_runner +44 -0
- data/bin/deploy +120 -0
- data/bin/enroll +385 -0
- data/bin/rad +32 -0
- data/bin/rchk +29 -0
- data/bin/rnac +39 -0
- data/bin/rs_connect +33 -0
- data/bin/rs_log_level +31 -0
- data/bin/rs_ohai +28 -0
- data/bin/rs_reenroll +31 -0
- data/bin/rs_run_recipe +34 -0
- data/bin/rs_run_right_script +34 -0
- data/bin/rs_shutdown +33 -0
- data/bin/rs_tag +33 -0
- data/bin/rs_thunk +33 -0
- data/bin/rstat +31 -0
- data/bin/system +16 -0
- data/ext/Rakefile +18 -0
- data/init/config.yml +5 -0
- data/init/init.rb +79 -0
- data/lib/chef/ohai_setup.rb +51 -0
- data/lib/chef/plugins/cloud.rb +91 -0
- data/lib/chef/plugins/cloudstack.rb +23 -0
- data/lib/chef/plugins/ec2.rb +23 -0
- data/lib/chef/plugins/linux/block_device2.rb +24 -0
- data/lib/chef/plugins/rackspace.rb +23 -0
- data/lib/chef/plugins/rightscale.rb +125 -0
- data/lib/chef/plugins/windows/network.rb +114 -0
- data/lib/chef/plugins.rb +74 -0
- data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
- data/lib/chef/providers/dns_resource.rb +100 -0
- data/lib/chef/providers/executable_schedule_provider.rb +70 -0
- data/lib/chef/providers/executable_schedule_resource.rb +144 -0
- data/lib/chef/providers/remote_recipe_provider.rb +86 -0
- data/lib/chef/providers/remote_recipe_resource.rb +101 -0
- data/lib/chef/providers/right_link_tag_provider.rb +73 -0
- data/lib/chef/providers/right_link_tag_resource.rb +59 -0
- data/lib/chef/providers/right_script_provider.rb +190 -0
- data/lib/chef/providers/right_script_resource.rb +113 -0
- data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
- data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
- data/lib/chef/providers/server_collection_provider.rb +66 -0
- data/lib/chef/providers/server_collection_resource.rb +93 -0
- data/lib/chef/providers/windows/powershell_provider.rb +151 -0
- data/lib/chef/providers/windows/powershell_resource.rb +111 -0
- data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
- data/lib/chef/right_providers.rb +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
- data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
- data/lib/chef/windows/chef_node_server.rb +463 -0
- data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
- data/lib/chef/windows/pipe_server.rb +283 -0
- data/lib/chef/windows/powershell_host.rb +285 -0
- data/lib/chef/windows/powershell_pipe_server.rb +136 -0
- data/lib/chef/windows/powershell_provider_base.rb +92 -0
- data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
- data/lib/clouds/cloud.rb +557 -0
- data/lib/clouds/cloud_factory.rb +250 -0
- data/lib/clouds/cloud_utilities.rb +244 -0
- data/lib/clouds/clouds/azure.rb +106 -0
- data/lib/clouds/clouds/cloudstack.rb +114 -0
- data/lib/clouds/clouds/ec2.rb +113 -0
- data/lib/clouds/clouds/eucalyptus.rb +46 -0
- data/lib/clouds/clouds/google.rb +102 -0
- data/lib/clouds/clouds/none.rb +76 -0
- data/lib/clouds/clouds/openstack.rb +30 -0
- data/lib/clouds/clouds/rackspace-ng.rb +54 -0
- data/lib/clouds/clouds/rackspace.rb +78 -0
- data/lib/clouds/clouds/softlayer.rb +91 -0
- data/lib/clouds/metadata_formatter.rb +108 -0
- data/lib/clouds/metadata_provider.rb +128 -0
- data/lib/clouds/metadata_source.rb +87 -0
- data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
- data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
- data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
- data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
- data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
- data/lib/clouds/metadata_tree_climber.rb +144 -0
- data/lib/clouds/metadata_writer.rb +155 -0
- data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
- data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
- data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
- data/lib/clouds/register_clouds.rb +34 -0
- data/lib/clouds.rb +32 -0
- data/lib/gem_dependencies.rb +83 -0
- data/lib/git_hooks/commit-msg.rb +7 -0
- data/lib/instance/agent_config.rb +168 -0
- data/lib/instance/agent_watcher.rb +233 -0
- data/lib/instance/audit_cook_stub.rb +104 -0
- data/lib/instance/audit_proxy.rb +247 -0
- data/lib/instance/bundle_queue.rb +104 -0
- data/lib/instance/cook/agent_connection.rb +109 -0
- data/lib/instance/cook/audit_logger.rb +165 -0
- data/lib/instance/cook/audit_stub.rb +142 -0
- data/lib/instance/cook/ca-bundle.crt +2794 -0
- data/lib/instance/cook/chef_state.rb +211 -0
- data/lib/instance/cook/cook.rb +306 -0
- data/lib/instance/cook/cook_state.rb +298 -0
- data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
- data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
- data/lib/instance/cook/executable_sequence.rb +765 -0
- data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
- data/lib/instance/cook/repose_downloader.rb +349 -0
- data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
- data/lib/instance/cook.rb +41 -0
- data/lib/instance/downloader.rb +208 -0
- data/lib/instance/duplicable.rb +67 -0
- data/lib/instance/exceptions.rb +49 -0
- data/lib/instance/executable_sequence_proxy.rb +278 -0
- data/lib/instance/instance_commands.rb +577 -0
- data/lib/instance/instance_state.rb +633 -0
- data/lib/instance/json_utilities.rb +102 -0
- data/lib/instance/login_manager.rb +533 -0
- data/lib/instance/login_user_manager.rb +522 -0
- data/lib/instance/message_encoder.rb +118 -0
- data/lib/instance/multi_thread_bundle_queue.rb +232 -0
- data/lib/instance/operation_context.rb +60 -0
- data/lib/instance/options_bag.rb +65 -0
- data/lib/instance/payload_formatter.rb +46 -0
- data/lib/instance/policy.rb +53 -0
- data/lib/instance/policy_audit.rb +100 -0
- data/lib/instance/policy_manager.rb +146 -0
- data/lib/instance/reenroll_manager.rb +104 -0
- data/lib/instance/right_scripts_cookbook.rb +181 -0
- data/lib/instance/shutdown_request.rb +221 -0
- data/lib/instance/single_thread_bundle_queue.rb +189 -0
- data/lib/instance/volume_management.rb +450 -0
- data/lib/instance.rb +50 -0
- data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
- data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
- data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
- data/lib/repo_conf_generators/rightscale_key.pub +17 -0
- data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
- data/lib/repo_conf_generators.rb +30 -0
- data/lib/run_shell.rb +28 -0
- data/scripts/agent_checker.rb +571 -0
- data/scripts/agent_controller.rb +247 -0
- data/scripts/agent_deployer.rb +148 -0
- data/scripts/bundle_runner.rb +336 -0
- data/scripts/cloud_controller.rb +176 -0
- data/scripts/log_level_manager.rb +142 -0
- data/scripts/ohai_runner.rb +33 -0
- data/scripts/reenroller.rb +193 -0
- data/scripts/server_importer.rb +293 -0
- data/scripts/shutdown_client.rb +183 -0
- data/scripts/system_configurator.rb +367 -0
- data/scripts/tagger.rb +381 -0
- data/scripts/thunker.rb +356 -0
- 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
|