right_link 5.9.0

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