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,193 @@
|
|
1
|
+
# === Synopsis:
|
2
|
+
# RightScale Re-enroller (rs_reenroll) - (c) 2010-2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# Re-enroller causes the instance to re-enroll
|
5
|
+
# CAUTION: This process may take a while to take place, during that time
|
6
|
+
# the agent will be un-responsive. Only use when the instance is in
|
7
|
+
# a bad state and you understand the consequences.
|
8
|
+
#
|
9
|
+
# === Usage
|
10
|
+
# rs_reenroll
|
11
|
+
#
|
12
|
+
# Options:
|
13
|
+
# --verbose, -v Display debug information
|
14
|
+
# --help: Display help
|
15
|
+
# --version: Display version information
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'rubygems'
|
19
|
+
require 'trollop'
|
20
|
+
require 'fileutils'
|
21
|
+
require 'right_agent'
|
22
|
+
require 'right_agent/scripts/usage'
|
23
|
+
require 'right_agent/scripts/common_parser'
|
24
|
+
|
25
|
+
require File.normalize_path(File.join(File.dirname(__FILE__), '..', 'lib', 'instance', 'agent_config'))
|
26
|
+
|
27
|
+
module RightScale
|
28
|
+
|
29
|
+
class Reenroller
|
30
|
+
|
31
|
+
if RightScale::Platform.windows?
|
32
|
+
# Note we currently only need a reenroller state file under windows.
|
33
|
+
STATE_DIR = AgentConfig.agent_state_dir
|
34
|
+
STATE_FILE = File.join(STATE_DIR, 'reenroller_state.js')
|
35
|
+
end
|
36
|
+
|
37
|
+
# Trigger re-enrollment
|
38
|
+
#
|
39
|
+
# === Return
|
40
|
+
# true:: Always return true
|
41
|
+
def run(options)
|
42
|
+
AgentConfig.root_dir = AgentConfig.right_link_root_dirs
|
43
|
+
|
44
|
+
if RightScale::Platform.windows?
|
45
|
+
cleanup_certificates(options)
|
46
|
+
# Write state file to indicate to RightScaleService that it should not
|
47
|
+
# enter the rebooting state (which is the default behavior when the
|
48
|
+
# RightScaleService starts).
|
49
|
+
reenroller_state = {:reenroll => true}
|
50
|
+
File.open(STATE_FILE, "w") { |f| f.write reenroller_state.to_json }
|
51
|
+
print 'Restarting RightScale service...' if options[:verbose]
|
52
|
+
res = system('net start RightScale')
|
53
|
+
puts to_ok(res) if options[:verbose]
|
54
|
+
else
|
55
|
+
print 'Stopping RightLink daemon...' if options[:verbose]
|
56
|
+
pid_file = AgentConfig.pid_file('instance')
|
57
|
+
pid = pid_file ? pid_file.read_pid[:pid] : nil
|
58
|
+
system('/opt/rightscale/bin/rchk --stop')
|
59
|
+
# Wait for agent process to terminate
|
60
|
+
retries = 0
|
61
|
+
while process_running?(pid) && retries < 40
|
62
|
+
sleep(0.5)
|
63
|
+
retries += 1
|
64
|
+
print '.' if options[:verbose]
|
65
|
+
end
|
66
|
+
puts to_ok(!process_running?(pid)) if options[:verbose]
|
67
|
+
# Kill it if it's still alive after ~ 20 sec
|
68
|
+
if process_running?(pid)
|
69
|
+
print 'Forcing RightLink daemon to exit...' if options[:verbose]
|
70
|
+
res = Process.kill('KILL', pid) rescue nil
|
71
|
+
puts to_ok(res) if options[:verbose]
|
72
|
+
end
|
73
|
+
cleanup_certificates(options)
|
74
|
+
|
75
|
+
# Resume option bypasses cloud state initialization so that we can
|
76
|
+
# override the user data
|
77
|
+
puts((options[:resume] ? 'Resuming' : 'Restarting') + ' RightLink daemon...') if options[:verbose]
|
78
|
+
action = (options[:resume] ? 'resume' : 'start')
|
79
|
+
res = system("/etc/init.d/rightlink #{action} > /dev/null")
|
80
|
+
end
|
81
|
+
true
|
82
|
+
rescue Errno::EACCES => e
|
83
|
+
STDERR.puts e.message
|
84
|
+
STDERR.puts "Try elevating privilege (sudo/runas) before invoking this command."
|
85
|
+
exit(2)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Create options hash from command line arguments
|
89
|
+
#
|
90
|
+
# === Return
|
91
|
+
# options(Hash):: Hash of options as defined by the command line
|
92
|
+
def parse_args
|
93
|
+
parser = Trollop::Parser.new do
|
94
|
+
opt :resume
|
95
|
+
opt :verbose
|
96
|
+
version ""
|
97
|
+
end
|
98
|
+
|
99
|
+
begin
|
100
|
+
parser.parse
|
101
|
+
rescue Trollop::HelpNeeded
|
102
|
+
puts Usage.scan(__FILE__)
|
103
|
+
exit
|
104
|
+
rescue Trollop::VersionNeeded
|
105
|
+
puts version
|
106
|
+
exit(0)
|
107
|
+
rescue Trollop::CommandlineError => e
|
108
|
+
puts e.message + "\nUse --help for additional information"
|
109
|
+
exit(1)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
# Map given value to [OK] or [ERROR]
|
116
|
+
# By default return [OK] unless value is false or nil
|
117
|
+
# Override default behavior by using 'ok_values' and/or 'error_values'
|
118
|
+
#
|
119
|
+
# === Parameters
|
120
|
+
# val(Object):: Value to be tested
|
121
|
+
# default_ok(Boolean):: Whether default value is '[OK]' (true) or '[ERROR]' (false), '[OK]' by default
|
122
|
+
# ok_values(Array):: Array of values that will cause +to_ok+ to return '[OK]' if defined, nil by default
|
123
|
+
# error_values(Array):: Array of values that will cause +to_ok+ to return '[ERROR]' if defined, [nil, false] by default
|
124
|
+
#
|
125
|
+
# === Return
|
126
|
+
# status(String):: [OK] or [ERROR]
|
127
|
+
def to_ok(val, default_value='[OK]', ok_values=nil, error_values=[nil, false])
|
128
|
+
return '[OK]' if ok_values && ok_values.include?(val)
|
129
|
+
return '[ERROR]' if error_values && error_values.include?(val)
|
130
|
+
return default_value
|
131
|
+
end
|
132
|
+
|
133
|
+
# Cleanup certificates
|
134
|
+
#
|
135
|
+
# === Parameters
|
136
|
+
# options(Hash):: Options hash
|
137
|
+
#
|
138
|
+
# === Return
|
139
|
+
# true:: Always return true
|
140
|
+
def cleanup_certificates(options)
|
141
|
+
puts 'Cleaning up certificates...' if options[:verbose]
|
142
|
+
AgentConfig.certs_files("*.{cert,key}").each { |f| FileUtils.rm_f(f) } # requires that root_dir already known in AgentConfig
|
143
|
+
end
|
144
|
+
|
145
|
+
# Checks whether process with given pid is running
|
146
|
+
#
|
147
|
+
# === Parameters
|
148
|
+
# pid(Fixnum):: Process id to be checked
|
149
|
+
#
|
150
|
+
# === Return
|
151
|
+
# true:: If process is running
|
152
|
+
# false:: Otherwise
|
153
|
+
def process_running?(pid)
|
154
|
+
return false unless pid
|
155
|
+
Process.getpgid(pid) != -1
|
156
|
+
rescue Errno::ESRCH
|
157
|
+
false
|
158
|
+
end
|
159
|
+
|
160
|
+
# Version information
|
161
|
+
#
|
162
|
+
# === Return
|
163
|
+
# (String):: Version information
|
164
|
+
def version
|
165
|
+
gemspec = eval(File.read(File.join(File.dirname(__FILE__), '..', 'right_link.gemspec')))
|
166
|
+
"rs_reenroll #{gemspec.version} - RightLink's reenroller (c) 2011 RightScale"
|
167
|
+
end
|
168
|
+
|
169
|
+
end # Reenroller
|
170
|
+
|
171
|
+
end # RightScale
|
172
|
+
|
173
|
+
#
|
174
|
+
# Copyright (c) 2009-2011 RightScale Inc
|
175
|
+
#
|
176
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
177
|
+
# a copy of this software and associated documentation files (the
|
178
|
+
# "Software"), to deal in the Software without restriction, including
|
179
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
180
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
181
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
182
|
+
# the following conditions:
|
183
|
+
#
|
184
|
+
# The above copyright notice and this permission notice shall be
|
185
|
+
# included in all copies or substantial portions of the Software.
|
186
|
+
#
|
187
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
188
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
189
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
190
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
191
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
192
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
193
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,293 @@
|
|
1
|
+
# === Synopsis:
|
2
|
+
# RightScale Server Import Utility (rs_connect) - (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# This utility allows an arbitrary virtual or physical machine to be
|
5
|
+
# managed by the RightScale dashboard.
|
6
|
+
#
|
7
|
+
# === Usage
|
8
|
+
# rs_connect --attach <url> [options]
|
9
|
+
#
|
10
|
+
# Options:
|
11
|
+
# --attach, -a Attach this machine to a server
|
12
|
+
# --force, -f Force attachment even if server appears already connected.
|
13
|
+
# --cloud, -c Name of cloud in which instance is running or 'none'
|
14
|
+
# to indicate instance is not running in any cloud. If a
|
15
|
+
# cloud has already been selected during installation of
|
16
|
+
# RightLink then this option will override that choice.
|
17
|
+
# If no choice has been made then the default is 'none'.
|
18
|
+
# --help: Display help
|
19
|
+
# --version: Display version information
|
20
|
+
#
|
21
|
+
# No options prints usage information.
|
22
|
+
#
|
23
|
+
|
24
|
+
require 'rubygems'
|
25
|
+
require 'trollop'
|
26
|
+
require 'uri'
|
27
|
+
require 'logger'
|
28
|
+
require 'net/http'
|
29
|
+
require 'fileutils'
|
30
|
+
require 'right_agent'
|
31
|
+
require 'right_agent/scripts/usage'
|
32
|
+
require 'right_agent/scripts/common_parser'
|
33
|
+
require 'right_http_connection'
|
34
|
+
require File.normalize_path(File.join(File.dirname(__FILE__), '..', 'lib', 'instance'))
|
35
|
+
|
36
|
+
module RightScale
|
37
|
+
|
38
|
+
class ServerImporter
|
39
|
+
# Exception class to use as a token that something went wrong with an HTTP query
|
40
|
+
class QueryFailed < Exception; end
|
41
|
+
|
42
|
+
# Exception class to use when the user data doesn't look right
|
43
|
+
class MalformedResponse < Exception; end
|
44
|
+
|
45
|
+
# Unsupported architecture or operating system
|
46
|
+
class UnsupportedPlatform < Exception; end
|
47
|
+
|
48
|
+
# Run
|
49
|
+
#
|
50
|
+
# === Parameters
|
51
|
+
# options(Hash):: Hash of options as defined in +parse_args+
|
52
|
+
#
|
53
|
+
# === Return
|
54
|
+
# true:: Always return true
|
55
|
+
def run(options)
|
56
|
+
configure_logging
|
57
|
+
|
58
|
+
case options[:action]
|
59
|
+
when :attach
|
60
|
+
# resolve cloud name.
|
61
|
+
cloud_file = RightScale::AgentConfig.cloud_file_path
|
62
|
+
cloud_name = options[:cloud]
|
63
|
+
if cloud_name.nil? && File.file?(cloud_file)
|
64
|
+
cloud_name = File.read(cloud_file).strip
|
65
|
+
end
|
66
|
+
cloud_name = 'none' if cloud_name.to_s.empty?
|
67
|
+
|
68
|
+
cloud_dir = File.dirname(cloud_file)
|
69
|
+
output_file = File.join(RightScale::Platform.filesystem.spool_dir, cloud_name, 'user-data.txt')
|
70
|
+
output_dir = File.dirname(output_file)
|
71
|
+
|
72
|
+
if File.exist?(InstanceState::STATE_FILE) && !options[:force]
|
73
|
+
puts "It appears this system is already managed by RightScale; cannot continue"
|
74
|
+
puts
|
75
|
+
puts "To override this decision, use the --force option. Please make sure you"
|
76
|
+
puts "know what you are doing! Connecting this system to a server when it is"
|
77
|
+
puts "already connected to another server could cause unexpected behavior in"
|
78
|
+
puts "the RightScale dashboard, and in certain cases, data loss!"
|
79
|
+
exit(-1)
|
80
|
+
end
|
81
|
+
|
82
|
+
puts "Fetching launch settings from RightScale"
|
83
|
+
url = options[:url]
|
84
|
+
data = http_get(url, false)
|
85
|
+
|
86
|
+
unless data =~ /RS_rn_id/i
|
87
|
+
Log.error("Malformed launch settings: #{data}")
|
88
|
+
raise MalformedResponse, "Launch settings do not look well-formed; did you specify the right URL?"
|
89
|
+
end
|
90
|
+
|
91
|
+
puts "Creating cloud-family hint file (#{cloud_file})"
|
92
|
+
FileUtils.mkdir_p(cloud_dir)
|
93
|
+
File.open(cloud_file, 'w') do |f|
|
94
|
+
f.puts cloud_name
|
95
|
+
end
|
96
|
+
|
97
|
+
puts "Writing launch settings to file"
|
98
|
+
FileUtils.mkdir_p(output_dir)
|
99
|
+
File.open(output_file, 'w') do |f|
|
100
|
+
f.puts data
|
101
|
+
end
|
102
|
+
|
103
|
+
puts "Done connecting server to RightScale. Will now attempt to start the RightLink services."
|
104
|
+
puts "If starting of services fails, you can attempt to start them by rebooting."
|
105
|
+
if RightScale::Platform.windows?
|
106
|
+
puts `net start rightscale`
|
107
|
+
exit $?.exitstatus unless $?.success?
|
108
|
+
elsif RightScale::Platform.linux? || RightScale::Platform.darwin?
|
109
|
+
puts `/etc/init.d/rightscale start && /etc/init.d/rightlink start`
|
110
|
+
exit $?.exitstatus unless $?.success?
|
111
|
+
else
|
112
|
+
raise UnsupportedPlatform, "Starting services is not supported for this platform."
|
113
|
+
end
|
114
|
+
exit
|
115
|
+
else
|
116
|
+
puts Usage.scan(__FILE__)
|
117
|
+
exit
|
118
|
+
end
|
119
|
+
rescue SystemExit => e
|
120
|
+
raise e
|
121
|
+
rescue Exception => e
|
122
|
+
fail(e)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Create options hash from command line arguments
|
126
|
+
#
|
127
|
+
# === Return
|
128
|
+
# options(Hash):: Hash of options as defined by the command line
|
129
|
+
def parse_args
|
130
|
+
options = { :verbose => false, :status => false, :immediately => false, :action => :attach}
|
131
|
+
|
132
|
+
parser = Trollop::Parser.new do
|
133
|
+
opt :url, "", :long => "--attach", :short => "-a", :type => String, :required => true
|
134
|
+
opt :force
|
135
|
+
opt :cloud, "", :type => String
|
136
|
+
version ""
|
137
|
+
end
|
138
|
+
|
139
|
+
begin
|
140
|
+
options.merge(parser.parse)
|
141
|
+
rescue Trollop::HelpNeeded
|
142
|
+
puts Usage.scan(__FILE__)
|
143
|
+
exit
|
144
|
+
rescue Trollop::CommandlineError => e
|
145
|
+
puts e.message + "\nUse --help for additional information"
|
146
|
+
exit(1)
|
147
|
+
rescue Trollop::VersionNeeded
|
148
|
+
puts version
|
149
|
+
succeed
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
protected
|
154
|
+
|
155
|
+
# Print error on console and exit abnormally
|
156
|
+
#
|
157
|
+
# === Parameter
|
158
|
+
# reason(String|Exception):: Error message or exception, default to nil (no message printed)
|
159
|
+
# print_usage(Boolean):: Whether script usage should be printed, default to false
|
160
|
+
#
|
161
|
+
# === Return
|
162
|
+
# R.I.P. does not return
|
163
|
+
def fail(reason=nil, print_usage=false)
|
164
|
+
case reason
|
165
|
+
when Errno::EACCES
|
166
|
+
STDERR.puts reason.message
|
167
|
+
STDERR.puts "Try elevating privilege (sudo/runas) before invoking this command."
|
168
|
+
code = 2
|
169
|
+
when Exception
|
170
|
+
STDERR.puts "** #{reason.message}"
|
171
|
+
code = 1
|
172
|
+
else
|
173
|
+
STDERR.puts "** #{reason}" if reason
|
174
|
+
code = 1
|
175
|
+
end
|
176
|
+
|
177
|
+
puts Usage.scan(__FILE__) if print_usage
|
178
|
+
exit(code)
|
179
|
+
end
|
180
|
+
|
181
|
+
# Version information
|
182
|
+
#
|
183
|
+
# === Return
|
184
|
+
# (String):: Version information
|
185
|
+
def version
|
186
|
+
gemspec = eval(File.read(File.join(File.dirname(__FILE__), '..', 'right_link.gemspec')))
|
187
|
+
"rs_connect #{gemspec.version} - RightLink's server importer (c) 2011 RightScale"
|
188
|
+
end
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
def configure_logging
|
193
|
+
Log.program_name = 'RightLink'
|
194
|
+
Log.facility = 'user'
|
195
|
+
Log.log_to_file_only(false)
|
196
|
+
Log.level = Logger::INFO
|
197
|
+
FileUtils.mkdir_p(File.dirname(InstanceState::BOOT_LOG_FILE))
|
198
|
+
Log.add_logger(Logger.new(File.open(InstanceState::BOOT_LOG_FILE, 'a')))
|
199
|
+
end
|
200
|
+
|
201
|
+
# Performs an HTTP get request with built-in retries and redirection based
|
202
|
+
# on HTTP responses.
|
203
|
+
#
|
204
|
+
# === Parameters
|
205
|
+
# attempts(int):: number of attempts
|
206
|
+
#
|
207
|
+
# === Return
|
208
|
+
# result(String):: body of response or nil
|
209
|
+
def http_get(path, keep_alive = true)
|
210
|
+
uri = safe_parse_http_uri(path)
|
211
|
+
history = []
|
212
|
+
loop do
|
213
|
+
Log.debug("http_get(#{uri})")
|
214
|
+
|
215
|
+
# keep history of live connections for more efficient redirection.
|
216
|
+
host = uri.host
|
217
|
+
connection = Rightscale::HttpConnection.new(:logger => Log, :exception => QueryFailed)
|
218
|
+
|
219
|
+
# prepare request. ensure path not empty due to Net::HTTP limitation.
|
220
|
+
#
|
221
|
+
# note that the default for Net::HTTP is to close the connection after
|
222
|
+
# each request (contrary to expected conventions). we must be explicit
|
223
|
+
# about keep-alive if we want that behavior.
|
224
|
+
request = Net::HTTP::Get.new(uri.path)
|
225
|
+
request['Connection'] = keep_alive ? 'keep-alive' : 'close'
|
226
|
+
|
227
|
+
# get.
|
228
|
+
response = connection.request(:protocol => uri.scheme, :server => uri.host, :port => uri.port, :request => request)
|
229
|
+
return response.body if response.kind_of?(Net::HTTPSuccess)
|
230
|
+
if response.kind_of?(Net::HTTPServerError) || response.kind_of?(Net::HTTPNotFound)
|
231
|
+
Log.debug("Request failed but can retry; #{response.class.name}")
|
232
|
+
return nil
|
233
|
+
elsif response.kind_of?(Net::HTTPRedirection)
|
234
|
+
# keep history of redirects.
|
235
|
+
location = response['Location']
|
236
|
+
uri = safe_parse_http_uri(location)
|
237
|
+
else
|
238
|
+
# not retryable.
|
239
|
+
#
|
240
|
+
# note that the EC2 metadata server is known to give malformed
|
241
|
+
# responses on rare occasions, but the right_http_connection will
|
242
|
+
# consider these to be 'bananas' and retry automatically (up to a
|
243
|
+
# pre-defined limit).
|
244
|
+
Log.error("HTTP request failed: #{response.class.name}")
|
245
|
+
raise QueryFailed, "HTTP request failed: #{response.class.name}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# Handles some cases which raise exceptions in the URI class.
|
251
|
+
#
|
252
|
+
# === Parameters
|
253
|
+
# path(String):: URI to parse
|
254
|
+
#
|
255
|
+
# === Return
|
256
|
+
# uri(URI):: parsed URI
|
257
|
+
#
|
258
|
+
# === Raise
|
259
|
+
# URI::InvalidURIError:: on invalid URI
|
260
|
+
def safe_parse_http_uri(path)
|
261
|
+
raise ArgumentError.new("URI path cannot be empty") if path.to_s.empty?
|
262
|
+
begin
|
263
|
+
uri = URI.parse(path)
|
264
|
+
rescue URI::InvalidURIError => e
|
265
|
+
# URI raises an exception for paths like "<IP>:<port>"
|
266
|
+
# (e.g. "127.0.0.1:123") unless they also have scheme (e.g. http)
|
267
|
+
# prefix.
|
268
|
+
raise e if path.start_with?("http://") || path.start_with?("https://")
|
269
|
+
uri = URI.parse("http://" + path)
|
270
|
+
uri = URI.parse("https://" + path) if uri.port == 443
|
271
|
+
path = uri.to_s
|
272
|
+
end
|
273
|
+
|
274
|
+
# supply any missing default values to make URI as complete as possible.
|
275
|
+
if uri.scheme.nil? || uri.host.nil?
|
276
|
+
scheme = (uri.port == 443) ? 'https' : 'http'
|
277
|
+
uri = URI.parse("#{scheme}://#{path}")
|
278
|
+
path = uri.to_s
|
279
|
+
end
|
280
|
+
if uri.path.to_s.empty?
|
281
|
+
uri = URI.parse("#{path}/")
|
282
|
+
path = uri.to_s
|
283
|
+
end
|
284
|
+
|
285
|
+
return uri
|
286
|
+
end
|
287
|
+
|
288
|
+
def succeed
|
289
|
+
exit(0)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# === Synopsis:
|
2
|
+
# RightScale System Shutdown Utility (rs_shutdown) - (c) 2011 RightScale Inc
|
3
|
+
#
|
4
|
+
# This utility allows the given system to be shutdown or rebooted.
|
5
|
+
#
|
6
|
+
# === Examples:
|
7
|
+
# Shutdown:
|
8
|
+
# rs_shutdown --reboot --immediately
|
9
|
+
# rs_shutdown -r -i
|
10
|
+
# rs_shutdown --stop --deferred
|
11
|
+
# rs_shutdown -s -d
|
12
|
+
# rs_shutdown --terminate
|
13
|
+
# rs_shutdown -t
|
14
|
+
#
|
15
|
+
# === Usage
|
16
|
+
# rs_shutdown [options]
|
17
|
+
#
|
18
|
+
# Options:
|
19
|
+
# --reboot, -r Request reboot.
|
20
|
+
# --stop, -s Request stop (boot volume is preserved).
|
21
|
+
# --terminate, -t Request termination (boot volume is discarded).
|
22
|
+
# --immediately, -i Request immediate shutdown (reboot, stop or terminate) bypassing any pending scripts and preserving instance state.
|
23
|
+
# --deferred, -d Request deferred shutdown (reboot, stop or terminate) pending finish of any remaining scripts (default).
|
24
|
+
# --verbose, -v Display debug information
|
25
|
+
# --help: Display help
|
26
|
+
# --version: Display version information
|
27
|
+
#
|
28
|
+
# No options prints the current RightLink agent log level
|
29
|
+
#
|
30
|
+
|
31
|
+
require 'rubygems'
|
32
|
+
require 'trollop'
|
33
|
+
require 'right_agent'
|
34
|
+
require 'right_agent/scripts/usage'
|
35
|
+
require 'right_agent/scripts/common_parser'
|
36
|
+
|
37
|
+
require File.normalize_path(File.join(File.dirname(__FILE__), '..', 'lib', 'instance', 'shutdown_request'))
|
38
|
+
|
39
|
+
module RightScale
|
40
|
+
|
41
|
+
class ShutdownClient
|
42
|
+
|
43
|
+
# Run
|
44
|
+
#
|
45
|
+
# === Parameters
|
46
|
+
# options(Hash):: Hash of options as defined in +parse_args+
|
47
|
+
#
|
48
|
+
# === Return
|
49
|
+
# true:: Always return true
|
50
|
+
def run(options)
|
51
|
+
fail("Missing required shutdown argument") unless options[:level]
|
52
|
+
cmd = {}
|
53
|
+
cmd[:name] = :set_shutdown_request
|
54
|
+
cmd[:level] = options[:level]
|
55
|
+
cmd[:immediately] = options[:immediately]
|
56
|
+
config_options = AgentConfig.agent_options('instance')
|
57
|
+
listen_port = config_options[:listen_port]
|
58
|
+
fail('Could not retrieve agent listen port') unless listen_port
|
59
|
+
client = CommandClient.new(listen_port, config_options[:cookie])
|
60
|
+
begin
|
61
|
+
client.send_command(cmd, options[:verbose]) do |response|
|
62
|
+
if response[:error]
|
63
|
+
fail("Failed #{cmd.inspect} with #{response[:error]}")
|
64
|
+
else
|
65
|
+
message = response[:level]
|
66
|
+
message += " immediately" if response[:immediately]
|
67
|
+
puts message
|
68
|
+
end
|
69
|
+
end
|
70
|
+
rescue Exception => e
|
71
|
+
fail(e.message)
|
72
|
+
end
|
73
|
+
true
|
74
|
+
rescue SystemExit => e
|
75
|
+
raise e
|
76
|
+
rescue Exception => e
|
77
|
+
fail(e)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Create options hash from command line arguments
|
81
|
+
#
|
82
|
+
# === Return
|
83
|
+
# options(Hash):: Hash of options as defined by the command line
|
84
|
+
def parse_args
|
85
|
+
options = { :verbose => false, :status => false, :immediately => false }
|
86
|
+
parser = Trollop::Parser.new do
|
87
|
+
opt :reboot
|
88
|
+
opt :stop
|
89
|
+
opt :terminate
|
90
|
+
opt :immediately
|
91
|
+
opt :deferred
|
92
|
+
opt :verbose
|
93
|
+
version ""
|
94
|
+
conflicts :deferred, :immediately
|
95
|
+
end
|
96
|
+
|
97
|
+
begin
|
98
|
+
options.merge!(parser.parse)
|
99
|
+
options[:level] = ::RightScale::ShutdownRequest::REBOOT if options[:reboot]
|
100
|
+
options[:level] = ::RightScale::ShutdownRequest::STOP if options[:stop]
|
101
|
+
options[:level] = ::RightScale::ShutdownRequest::TERMINATE if options[:terminate]
|
102
|
+
options[:immediately] = false if options[:deferred]
|
103
|
+
rescue Trollop::VersionNeeded
|
104
|
+
puts version
|
105
|
+
succeed
|
106
|
+
rescue Trollop::HelpNeeded
|
107
|
+
puts Usage.scan(__FILE__)
|
108
|
+
exit
|
109
|
+
rescue SystemExit => e
|
110
|
+
raise e
|
111
|
+
rescue Exception => e
|
112
|
+
puts e.message + "\nUse --help for additional information"
|
113
|
+
exit(1)
|
114
|
+
end
|
115
|
+
options
|
116
|
+
end
|
117
|
+
|
118
|
+
protected
|
119
|
+
|
120
|
+
# Print error on console and exit abnormally
|
121
|
+
#
|
122
|
+
# === Parameter
|
123
|
+
# reason(String|Exception):: Error message or exception, default to nil (no message printed)
|
124
|
+
# print_usage(Boolean):: Whether script usage should be printed, default to false
|
125
|
+
#
|
126
|
+
# === Return
|
127
|
+
# R.I.P. does not return
|
128
|
+
def fail(reason=nil, print_usage=false)
|
129
|
+
case reason
|
130
|
+
when Errno::EACCES
|
131
|
+
STDERR.puts "** #{reason.message}"
|
132
|
+
STDERR.puts "** Try elevating privilege (sudo/runas) before invoking this command."
|
133
|
+
code = 2
|
134
|
+
when Exception
|
135
|
+
STDERR.puts "** #{reason.message}"
|
136
|
+
code = 1
|
137
|
+
else
|
138
|
+
STDERR.puts "** #{reason}" if reason
|
139
|
+
code = 1
|
140
|
+
end
|
141
|
+
|
142
|
+
puts Usage.scan(__FILE__) if print_usage
|
143
|
+
exit(code)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Version information
|
147
|
+
#
|
148
|
+
# === Return
|
149
|
+
# (String):: Version information
|
150
|
+
def version
|
151
|
+
gemspec = eval(File.read(File.join(File.dirname(__FILE__), '..', 'right_link.gemspec')))
|
152
|
+
"rs_shutdown #{gemspec.version} - RightLink's shutdown client (c) 2011 RightScale"
|
153
|
+
end
|
154
|
+
|
155
|
+
def succeed
|
156
|
+
exit(0)
|
157
|
+
end
|
158
|
+
|
159
|
+
end # ShutdownClient
|
160
|
+
|
161
|
+
end # RightScale
|
162
|
+
|
163
|
+
#
|
164
|
+
# Copyright (c) 2011 RightScale Inc
|
165
|
+
#
|
166
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
167
|
+
# a copy of this software and associated documentation files (the
|
168
|
+
# "Software"), to deal in the Software without restriction, including
|
169
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
170
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
171
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
172
|
+
# the following conditions:
|
173
|
+
#
|
174
|
+
# The above copyright notice and this permission notice shall be
|
175
|
+
# included in all copies or substantial portions of the Software.
|
176
|
+
#
|
177
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
178
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
179
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
180
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
181
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
182
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
183
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|