right_link 5.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. data/actors/agent_manager.rb +88 -0
  2. data/actors/instance_scheduler.rb +321 -0
  3. data/actors/instance_services.rb +64 -0
  4. data/actors/instance_setup.rb +567 -0
  5. data/bin/cloud +25 -0
  6. data/bin/cook_runner +44 -0
  7. data/bin/deploy +120 -0
  8. data/bin/enroll +385 -0
  9. data/bin/rad +32 -0
  10. data/bin/rchk +29 -0
  11. data/bin/rnac +39 -0
  12. data/bin/rs_connect +33 -0
  13. data/bin/rs_log_level +31 -0
  14. data/bin/rs_ohai +28 -0
  15. data/bin/rs_reenroll +31 -0
  16. data/bin/rs_run_recipe +34 -0
  17. data/bin/rs_run_right_script +34 -0
  18. data/bin/rs_shutdown +33 -0
  19. data/bin/rs_tag +33 -0
  20. data/bin/rs_thunk +33 -0
  21. data/bin/rstat +31 -0
  22. data/bin/system +16 -0
  23. data/ext/Rakefile +18 -0
  24. data/init/config.yml +5 -0
  25. data/init/init.rb +79 -0
  26. data/lib/chef/ohai_setup.rb +51 -0
  27. data/lib/chef/plugins/cloud.rb +91 -0
  28. data/lib/chef/plugins/cloudstack.rb +23 -0
  29. data/lib/chef/plugins/ec2.rb +23 -0
  30. data/lib/chef/plugins/linux/block_device2.rb +24 -0
  31. data/lib/chef/plugins/rackspace.rb +23 -0
  32. data/lib/chef/plugins/rightscale.rb +125 -0
  33. data/lib/chef/plugins/windows/network.rb +114 -0
  34. data/lib/chef/plugins.rb +74 -0
  35. data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
  36. data/lib/chef/providers/dns_resource.rb +100 -0
  37. data/lib/chef/providers/executable_schedule_provider.rb +70 -0
  38. data/lib/chef/providers/executable_schedule_resource.rb +144 -0
  39. data/lib/chef/providers/remote_recipe_provider.rb +86 -0
  40. data/lib/chef/providers/remote_recipe_resource.rb +101 -0
  41. data/lib/chef/providers/right_link_tag_provider.rb +73 -0
  42. data/lib/chef/providers/right_link_tag_resource.rb +59 -0
  43. data/lib/chef/providers/right_script_provider.rb +190 -0
  44. data/lib/chef/providers/right_script_resource.rb +113 -0
  45. data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
  46. data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
  47. data/lib/chef/providers/server_collection_provider.rb +66 -0
  48. data/lib/chef/providers/server_collection_resource.rb +93 -0
  49. data/lib/chef/providers/windows/powershell_provider.rb +151 -0
  50. data/lib/chef/providers/windows/powershell_resource.rb +111 -0
  51. data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
  52. data/lib/chef/right_providers.rb +55 -0
  53. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
  54. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
  55. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
  56. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
  57. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
  58. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
  59. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
  60. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
  61. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
  62. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
  63. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
  64. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
  65. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
  66. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
  67. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
  68. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
  69. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
  70. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
  71. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
  72. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
  73. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
  74. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  75. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
  76. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
  77. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
  78. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
  79. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
  80. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
  81. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
  82. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
  83. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
  84. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
  85. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
  86. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
  87. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
  88. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
  89. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
  90. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
  91. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
  92. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
  93. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  94. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
  95. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
  96. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
  97. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
  98. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
  99. data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
  100. data/lib/chef/windows/chef_node_server.rb +463 -0
  101. data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
  102. data/lib/chef/windows/pipe_server.rb +283 -0
  103. data/lib/chef/windows/powershell_host.rb +285 -0
  104. data/lib/chef/windows/powershell_pipe_server.rb +136 -0
  105. data/lib/chef/windows/powershell_provider_base.rb +92 -0
  106. data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
  107. data/lib/clouds/cloud.rb +557 -0
  108. data/lib/clouds/cloud_factory.rb +250 -0
  109. data/lib/clouds/cloud_utilities.rb +244 -0
  110. data/lib/clouds/clouds/azure.rb +106 -0
  111. data/lib/clouds/clouds/cloudstack.rb +114 -0
  112. data/lib/clouds/clouds/ec2.rb +113 -0
  113. data/lib/clouds/clouds/eucalyptus.rb +46 -0
  114. data/lib/clouds/clouds/google.rb +102 -0
  115. data/lib/clouds/clouds/none.rb +76 -0
  116. data/lib/clouds/clouds/openstack.rb +30 -0
  117. data/lib/clouds/clouds/rackspace-ng.rb +54 -0
  118. data/lib/clouds/clouds/rackspace.rb +78 -0
  119. data/lib/clouds/clouds/softlayer.rb +91 -0
  120. data/lib/clouds/metadata_formatter.rb +108 -0
  121. data/lib/clouds/metadata_provider.rb +128 -0
  122. data/lib/clouds/metadata_source.rb +87 -0
  123. data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
  124. data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
  125. data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
  126. data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
  127. data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
  128. data/lib/clouds/metadata_tree_climber.rb +144 -0
  129. data/lib/clouds/metadata_writer.rb +155 -0
  130. data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
  131. data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
  132. data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
  133. data/lib/clouds/register_clouds.rb +34 -0
  134. data/lib/clouds.rb +32 -0
  135. data/lib/gem_dependencies.rb +83 -0
  136. data/lib/git_hooks/commit-msg.rb +7 -0
  137. data/lib/instance/agent_config.rb +168 -0
  138. data/lib/instance/agent_watcher.rb +233 -0
  139. data/lib/instance/audit_cook_stub.rb +104 -0
  140. data/lib/instance/audit_proxy.rb +247 -0
  141. data/lib/instance/bundle_queue.rb +104 -0
  142. data/lib/instance/cook/agent_connection.rb +109 -0
  143. data/lib/instance/cook/audit_logger.rb +165 -0
  144. data/lib/instance/cook/audit_stub.rb +142 -0
  145. data/lib/instance/cook/ca-bundle.crt +2794 -0
  146. data/lib/instance/cook/chef_state.rb +211 -0
  147. data/lib/instance/cook/cook.rb +306 -0
  148. data/lib/instance/cook/cook_state.rb +298 -0
  149. data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
  150. data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
  151. data/lib/instance/cook/executable_sequence.rb +765 -0
  152. data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
  153. data/lib/instance/cook/repose_downloader.rb +349 -0
  154. data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
  155. data/lib/instance/cook.rb +41 -0
  156. data/lib/instance/downloader.rb +208 -0
  157. data/lib/instance/duplicable.rb +67 -0
  158. data/lib/instance/exceptions.rb +49 -0
  159. data/lib/instance/executable_sequence_proxy.rb +278 -0
  160. data/lib/instance/instance_commands.rb +577 -0
  161. data/lib/instance/instance_state.rb +633 -0
  162. data/lib/instance/json_utilities.rb +102 -0
  163. data/lib/instance/login_manager.rb +533 -0
  164. data/lib/instance/login_user_manager.rb +522 -0
  165. data/lib/instance/message_encoder.rb +118 -0
  166. data/lib/instance/multi_thread_bundle_queue.rb +232 -0
  167. data/lib/instance/operation_context.rb +60 -0
  168. data/lib/instance/options_bag.rb +65 -0
  169. data/lib/instance/payload_formatter.rb +46 -0
  170. data/lib/instance/policy.rb +53 -0
  171. data/lib/instance/policy_audit.rb +100 -0
  172. data/lib/instance/policy_manager.rb +146 -0
  173. data/lib/instance/reenroll_manager.rb +104 -0
  174. data/lib/instance/right_scripts_cookbook.rb +181 -0
  175. data/lib/instance/shutdown_request.rb +221 -0
  176. data/lib/instance/single_thread_bundle_queue.rb +189 -0
  177. data/lib/instance/volume_management.rb +450 -0
  178. data/lib/instance.rb +50 -0
  179. data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
  180. data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
  181. data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
  182. data/lib/repo_conf_generators/rightscale_key.pub +17 -0
  183. data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
  184. data/lib/repo_conf_generators.rb +30 -0
  185. data/lib/run_shell.rb +28 -0
  186. data/scripts/agent_checker.rb +571 -0
  187. data/scripts/agent_controller.rb +247 -0
  188. data/scripts/agent_deployer.rb +148 -0
  189. data/scripts/bundle_runner.rb +336 -0
  190. data/scripts/cloud_controller.rb +176 -0
  191. data/scripts/log_level_manager.rb +142 -0
  192. data/scripts/ohai_runner.rb +33 -0
  193. data/scripts/reenroller.rb +193 -0
  194. data/scripts/server_importer.rb +293 -0
  195. data/scripts/shutdown_client.rb +183 -0
  196. data/scripts/system_configurator.rb +367 -0
  197. data/scripts/tagger.rb +381 -0
  198. data/scripts/thunker.rb +356 -0
  199. metadata +418 -0
@@ -0,0 +1,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.