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
data/bin/deploy ADDED
@@ -0,0 +1,120 @@
1
+ # Copyright (c) 2009-2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gem_dependencies'))
23
+
24
+ # Standard library dependencies
25
+ require 'uri'
26
+ require 'fileutils'
27
+
28
+ # Gem dependencies
29
+ require 'right_agent'
30
+
31
+ # RightLink dependencies
32
+ require File.normalize_path(File.join(File.dirname(__FILE__), '..', 'lib', 'instance', 'agent_config'))
33
+ require File.normalize_path(File.join(File.dirname(__FILE__), '..', 'lib', 'instance', 'instance_state'))
34
+
35
+ module RightScale
36
+
37
+ class AgentDeployerRunner
38
+
39
+ def self.run
40
+ client = AgentDeployerRunner.new
41
+ Kernel.exit client.deploy
42
+ end
43
+
44
+ def deploy
45
+ configure_logging
46
+ read_userdata
47
+ invoke_rad
48
+ end
49
+
50
+ protected
51
+
52
+ def configure_logging
53
+ Log.program_name = 'RightLink'
54
+ Log.facility = 'user'
55
+ Log.log_to_file_only(false)
56
+ Log.level = Logger::INFO
57
+ FileUtils.mkdir_p(File.dirname(InstanceState::BOOT_LOG_FILE))
58
+ Log.add_logger(Logger.new(File.open(InstanceState::BOOT_LOG_FILE, 'a')))
59
+ Log.add_logger(Logger.new(STDOUT))
60
+ end
61
+
62
+ def read_userdata
63
+ dir = AgentConfig.cloud_state_dir
64
+ file = File.join(dir, 'user-data.rb')
65
+ load file
66
+ end
67
+
68
+ def invoke_rad
69
+ # Form RabbitMQ broker host:id list from RS_RN_URL and RS_RN_HOST
70
+ url = URI.parse(ENV['RS_RN_URL'])
71
+ host = ENV['RS_RN_HOST']
72
+ if !host
73
+ host = url.host
74
+ elsif host[0,1] == ':' || host[0,1] == ','
75
+ host = "#{url.host}#{host}"
76
+ end
77
+
78
+ root_dirs = AgentConfig.right_link_root_dirs.map { |x| ['-r', x] }.flatten
79
+
80
+ cmd_opts = [ 'instance' ] +
81
+ root_dirs +
82
+ [
83
+ '-i', ENV['RS_RN_ID'],
84
+ '-t', ENV['RS_RN_AUTH'],
85
+ '-h', host,
86
+ '-u', url.user,
87
+ '-p', url.password,
88
+ '-v', url.path,
89
+ '-b', 60,
90
+ '-q',
91
+ '-S'
92
+ ]
93
+
94
+ if ENV['http_proxy']
95
+ cmd_opts << ['--http-proxy', ENV['http_proxy']]
96
+ end
97
+
98
+ if ENV['no_proxy']
99
+ cmd_opts << ['--http-no-proxy', ENV['no_proxy']]
100
+ end
101
+
102
+ rad_path = if Platform.windows?
103
+ File.join(Platform.filesystem.right_link_home_dir, "bin")
104
+ else
105
+ Platform.filesystem.private_bin_dir
106
+ end
107
+ cmd = Platform.shell.format_executable_command(File.join(rad_path, 'rad'), cmd_opts)
108
+
109
+ Log.info("Deploying agent with command: #{cmd}")
110
+ exec(cmd)
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+ # The $0 argument is -e in windows because of how we wrap the call to get live
118
+ # console output. we don't need to worry about symlinks in Windows, so always
119
+ # run the deployer on that platform
120
+ RightScale::AgentDeployerRunner.run
data/bin/enroll ADDED
@@ -0,0 +1,385 @@
1
+ # Copyright (c) 2009-2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gem_dependencies'))
23
+
24
+ # Standard library dependencies
25
+ require 'optparse'
26
+ require 'fileutils'
27
+ require 'uri'
28
+
29
+ # Gem dependencies
30
+ require 'json'
31
+ require 'yaml'
32
+ require 'right_agent'
33
+
34
+ # RightLink dependencies
35
+ lib_dir = File.join(File.dirname(__FILE__), '..', 'lib')
36
+ require File.normalize_path(File.join(lib_dir, 'instance', 'agent_config'))
37
+ require File.normalize_path(File.join(lib_dir, 'instance', 'instance_state'))
38
+
39
+ # This environment variable prevents our AMQP error handler from logging errors
40
+ # This is needed because when the fetch enroll result code first tries to connect
41
+ # the queue may not exist yet and thus we would log errors when that is the expected
42
+ # behavior
43
+ ENV['IGNORE_AMQP_FAILURES'] = '1'
44
+
45
+ module RightScale
46
+
47
+ class AgentEnroller
48
+ ENROLL_USER = 'enrollment'
49
+ ENROLL_PASSWORD = 'enrollment'
50
+ RETRY_DEFAULT = 3600*96 # by default, try to enroll for 96 hours max
51
+ PRE_WAIT = 5 # fixed time to wait between sending enroll request and reconnecting as the account user
52
+ WAIT_MIN = 4 # min time to wait for an enroll response before retry
53
+ WAIT_MAX = 64 # max time to wait for an enroll response before retry
54
+ TERMINATE_ON_FAILURE_WINDOW = 45*60..60*60 # Terminate on failure if flag is set in user data AND failure
55
+ # occurred between 45 and 60 minutes of the initial boot
56
+ def self.run()
57
+ client = AgentEnroller.new
58
+ Kernel.exit client.enroll(client.parse_options)
59
+ end
60
+
61
+ def parse_options
62
+ options = {}
63
+
64
+ parser = OptionParser.new do |cli|
65
+ cli.on('--root-dir DIR') do |d|
66
+ # Allow for more than one
67
+ if options[:root_dir]
68
+ options[:root_dir] = [options[:root_dir]] unless options[:root_dir].is_a?(Array)
69
+ options[:root_dir] << d
70
+ else
71
+ options[:root_dir] = d
72
+ end
73
+ end
74
+ cli.on('-u', '--url URL') do |url|
75
+ options[:url] = url
76
+ end
77
+ cli.on('-h', '--host HOST') do |host|
78
+ options[:host] = host
79
+ end
80
+ cli.on('-p', '--port PORT') do |port|
81
+ # Only used for testing
82
+ options[:port] = port
83
+ end
84
+ cli.on('-i', '--id ID') do |id|
85
+ options[:id] = id.to_i
86
+ end
87
+ cli.on('-t', '--token TOKEN') do |token|
88
+ options[:token] = token
89
+ end
90
+ cli.on('-d', '--or-die') do
91
+ options[:die] = true
92
+ end
93
+ cli.on('-s', '--state FILE') do |file|
94
+ options[:state] = file
95
+ end
96
+ cli.on('-r', '--retry TIME') do |time|
97
+ options[:retry] = time.to_i
98
+ end
99
+ cli.on('--help') do
100
+ usage
101
+ end
102
+ end
103
+
104
+ begin
105
+ parser.parse(ARGV)
106
+
107
+ AgentConfig.root_dir = options[:root_dir]
108
+
109
+ # Fill in some default options
110
+ options[:state] ||= File.join(AgentConfig.agent_state_dir, 'enrollment_state.js')
111
+ options[:die] ||= false
112
+ options[:retry] ||= RETRY_DEFAULT
113
+
114
+ # Ensure all required options are present
115
+ missing = []
116
+ [:url, :id, :token].each { |req| missing << req unless options[req] }
117
+ raise ArgumentError, "Missing required option(s) #{missing.inspect}" unless missing.empty?
118
+
119
+ rescue SystemExit => e
120
+ # In case someone (e.g. RDoc usage) decided to bail
121
+ raise e
122
+
123
+ rescue Exception => e
124
+ puts e.message + "\nUse --help for additional information"
125
+ exit 1
126
+ end
127
+
128
+ return options
129
+ end
130
+
131
+ def enroll(options)
132
+ url = URI.parse(options[:url])
133
+ token_id = options[:id]
134
+ auth_token = options[:token]
135
+ started_at = Time.now
136
+ retry_for = options[:retry]
137
+ retry_until = Time.at(started_at.to_i + retry_for)
138
+ wait = WAIT_MIN
139
+
140
+ enroll_url = url.dup
141
+ enroll_url.user = ENROLL_USER
142
+ enroll_url.password = ENROLL_PASSWORD
143
+
144
+ host = if !options[:host]
145
+ url.host
146
+ elsif options[:host][0,1] == ':' || options[:host][0,1] == ','
147
+ "#{url.host}#{options[:host]}"
148
+ else
149
+ options[:host]
150
+ end
151
+
152
+ port = options[:port] || url.port || ::AMQP::PORT
153
+
154
+ configure_logging
155
+
156
+ create_state_file(options, started_at)
157
+
158
+ while !@result && (Time.now < retry_until)
159
+ t0 = Time.now
160
+
161
+ begin
162
+ Log.info("Requesting RightLink enrollment (token_id=#{token_id}; timestamp=#{t0.to_i})...")
163
+ request_enrollment(t0, enroll_url, host, port, token_id, auth_token, WAIT_MIN)
164
+
165
+ sleep(PRE_WAIT)
166
+
167
+ Log.info("Fetching response (will wait #{wait} seconds)...")
168
+ @result = fetch_enrollment_result(t0, url, host, port, token_id, auth_token, wait)
169
+
170
+ if @result
171
+ Log.info('Enrollment response received.')
172
+ else
173
+ raise StandardError, 'No enrollment response.'
174
+ end
175
+
176
+ rescue Interrupt => e
177
+ Log.info('Interrupt received; abandoning enrollment.')
178
+ return -2
179
+
180
+ rescue Exception => e
181
+ Log.error(e.message)
182
+
183
+ check_shutdown(options, started_at)
184
+
185
+ t1 = Time.now.utc
186
+ dt = t1 - t0
187
+ unless wait-dt <= 0
188
+ Log.info("Sleeping for #{(wait-dt).to_i} more seconds.")
189
+ sleep(wait-dt)
190
+ end
191
+
192
+ wait = [wait*2, WAIT_MAX].min
193
+ end
194
+ end
195
+
196
+ if @result
197
+ # Create the standard RightAgent certs_dir so we can write our certs there.
198
+ certs_dir = AgentConfig.certs_dir
199
+ FileUtils.mkdir_p(certs_dir) unless File.directory?(certs_dir)
200
+
201
+ # Write the mapper cert, our cert, and our private kjey
202
+ File.open(File.join(certs_dir, 'mapper.cert'), "w") do |f|
203
+ f.write(@result.mapper_cert)
204
+ end
205
+ File.open(File.join(certs_dir, 'instance.cert'), "w") do |f|
206
+ f.write(@result.id_cert)
207
+ end
208
+ instance_key = File.join(certs_dir, 'instance.key')
209
+ File.open(instance_key, "w") do |f|
210
+ f.write(@result.id_key)
211
+ FileUtils.chmod(0600, instance_key)
212
+ end
213
+
214
+ return 0
215
+ else
216
+ Log.error("Could not complete enrollment after #{retry_for} sec; aborting!!!")
217
+ return -1
218
+ end
219
+ end
220
+
221
+ protected
222
+
223
+ def configure_logging
224
+ Log.program_name = 'RightLink'
225
+ Log.facility = 'user'
226
+ Log.log_to_file_only(false)
227
+ Log.level = Logger::INFO
228
+ FileUtils.mkdir_p(File.dirname(InstanceState::BOOT_LOG_FILE))
229
+ Log.add_logger(Logger.new(File.open(InstanceState::BOOT_LOG_FILE, 'a')))
230
+ Log.add_logger(Logger.new(STDOUT))
231
+ end
232
+
233
+ def predict_agent_identity(token_id, auth_token)
234
+ public_token = SecureIdentity.derive(token_id, auth_token)
235
+ return AgentIdentity.new('rs', 'instance', token_id, public_token).to_s
236
+ end
237
+
238
+ def predict_queue_name(token_id, token)
239
+ return predict_agent_identity(token_id, token)
240
+ end
241
+
242
+ def shutdown_broker_and_em(broker, clean)
243
+ Log.error("Could not (re)connect. Auth failure? Broker offline?") unless clean
244
+ broker.close { EM.stop }
245
+ true
246
+ end
247
+
248
+ # Connect to AMQP broker and post an enrollment request
249
+ def request_enrollment(timestamp, url, host, port, token_id, token, wait)
250
+ EM.run do
251
+ options = {:host => host, :port => port, :user => url.user, :pass => url.password, :vhost => url.path}
252
+ broker = RightAMQP::HABrokerClient.new(serializer = nil, options)
253
+ broker.connection_status(:one_off => wait) do |status|
254
+ if status == :connected
255
+ request = {
256
+ :r_s_version => AgentConfig.protocol_version.to_s,
257
+ :agent_identity => predict_agent_identity(token_id, token),
258
+ :timestamp => timestamp.to_i.to_s,
259
+ :token_id => token_id,
260
+ :verifier => SecureIdentity.create_verifier(token_id, token, timestamp),
261
+ :host => options[:host],
262
+ :port => options[:port]
263
+ }
264
+ exchange = {:type => :direct, :name => "enrollment"}
265
+ serializer = Serializer.new
266
+ broker.publish(exchange, serializer.dump(request))
267
+ shutdown_broker_and_em(broker, true)
268
+ else
269
+ shutdown_broker_and_em(broker, false)
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ # Connect to AMQP broker, subscribe to our queue, and wait for an enrollment response
276
+ def fetch_enrollment_result(timestamp, url, host, port, token_id, token, wait)
277
+ retries = 0
278
+ result = nil
279
+
280
+ begin
281
+ drain = false
282
+ EM.run do
283
+ options = {:host => host, :port => port, :user => url.user, :pass => url.password, :vhost => url.path}
284
+ broker = RightAMQP::HABrokerClient.new(serializer = nil, options)
285
+ EM.add_timer(wait) { shutdown_broker_and_em(broker, true) }
286
+ queue = {:name => predict_queue_name(token_id, token), :options => {:no_declare => true, :durable => true}}
287
+ broker.subscribe(queue) do |b, msg|
288
+ begin
289
+ if drain
290
+ Log.info("Discarding message (in drain mode after receiving a bad packet)")
291
+ else
292
+ Log.info("Received enrollment response via broker #{b}")
293
+ result = EnrollmentResult.load(msg, token)
294
+ if result && (result.timestamp.to_i != timestamp.to_i)
295
+ raise EnrollmentResult::IntegrityFailure.new("Wrong timestamp: expected #{timestamp.to_i}; "+
296
+ "got #{result.timestamp.to_i}")
297
+ end
298
+ shutdown_broker_and_em(broker, true)
299
+ end
300
+ rescue Exception => e
301
+ Log.error("Received bad result packet", e)
302
+ drain = true
303
+ end
304
+ end
305
+ end
306
+ rescue Exception => e
307
+ # The initial calls to this function may fail because enroll has not yet created the queue
308
+ if e.message =~ /NOT_FOUND - no queue/
309
+ if (retries += 1) < 2
310
+ host = host.dup.split(",").reverse.join(",") if host
311
+ port = port.dup.split(",").reverse.join(",") if port && port.is_a?(String)
312
+ Log.info("Retrying fetch using host #{host} port #{port} after queue not found error")
313
+ sleep(1)
314
+ retry
315
+ end
316
+ else
317
+ raise e
318
+ end
319
+ end
320
+
321
+ result
322
+ end
323
+
324
+ # Create a state file indicating the options we were invoked with in addition
325
+ # to the time at which we first started to enroll. Intended for later use by
326
+ # the RightLink agent or other components.
327
+ def create_state_file(options, started_at)
328
+ state_file = options[:state]
329
+
330
+ unless File.exists?(state_file)
331
+ FileUtils.mkdir_p(File.dirname(state_file))
332
+ File.open(state_file, 'w') do |f|
333
+ state = options.merge(:started_at=>started_at.to_i)
334
+ f.write(JSON.dump(state))
335
+ end
336
+ end
337
+ end
338
+
339
+ # Shutdown if the 'die' flag is set and enroll failed during initial boot
340
+ # in the terminate on failure window.
341
+ def check_shutdown(options, started_at)
342
+ unless File.exists?(RightScale::InstanceState::STATE_FILE)
343
+ elapsed_since_init_boot = Time.now - started_at
344
+ if options[:die] && TERMINATE_ON_FAILURE_WINDOW.include?(elapsed_since_init_boot)
345
+ Log.error("Shutting down after trying to enroll for #{elapsed_since_init_boot / 60} minutes")
346
+ RightScale::Platform.controller.shutdown
347
+ Kernel.exit(-1)
348
+ end
349
+ end
350
+ end
351
+
352
+ def usage
353
+ puts <<EOF
354
+ Synopsis:
355
+ RightLink Agent Enrollment Tool (enroll) - (c) 2009-2011 RightScale
356
+
357
+ enroll is a command-line tool that retrieves agent configuration
358
+ and credentials from RightScale servers in a secure manner
359
+
360
+ Usage:
361
+ enroll.rb --root-dir DIR --url URL --host HOST --port PORT --id ID --token TOKEN
362
+ [--state FILE --or-die --retry TIME]
363
+
364
+ options:
365
+ --root-dir DIR Root directory of right_link
366
+ --url, -u URL AMQP connection URL (user/pass/host/port/vhost)
367
+ --host, -h HOST AMQP connection host:id comma-separated list
368
+ with first host defaulting to the one in URL, e.g.,
369
+ ":0,another_host:3"
370
+ --port, -p PORT AMQP connection port:id comma-separated list, corresponding
371
+ to host list; if only one port, it is used for all hosts
372
+ --id, -i ID Authenticate as agent ID
373
+ --token, -t TOKEN Use TOKEN to sign and encrypt AMQP messages
374
+ --or-die, -d Shutdown machine if not enrolled after 45 minutes
375
+ --retry, -r TIME Retry for TIME seconds before giving up permanently
376
+ --state, -s FILE Keep enrollment state (timestamps, etc) in FILE
377
+ EOF
378
+ exit -2
379
+ end
380
+
381
+ end # AgentEnroller
382
+
383
+ end # RightScale
384
+
385
+ RightScale::AgentEnroller.run
data/bin/rad ADDED
@@ -0,0 +1,32 @@
1
+ # Copyright (c) 2009-2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ # rad --help for usage information
23
+ #
24
+ # See scripts/agent_deployer.rb for additional information.
25
+
26
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gem_dependencies'))
27
+
28
+ $:.push(File.join(File.dirname(__FILE__), '..', 'scripts'))
29
+ require 'agent_deployer'
30
+
31
+ RightScale::RightLinkAgentDeployer.run
32
+
data/bin/rchk ADDED
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2009-2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ # See scripts/agent_checker.rb for additional information.
23
+
24
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gem_dependencies'))
25
+
26
+ $:.push(File.join(File.dirname(__FILE__), '..', 'scripts'))
27
+ require 'agent_checker'
28
+
29
+ RightScale::AgentChecker.run
data/bin/rnac ADDED
@@ -0,0 +1,39 @@
1
+ # Copyright (c) 2009-2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ # rnac --help for usage information
23
+ #
24
+ # See scripts/agent_controller.rb for additional information.
25
+
26
+ # Monit cleans the environment before running a daemon
27
+ # We can re-set any necessary environment here
28
+ #
29
+ # FIX: HOME appears to mean nothing in Windows (whereas HOMEPATH is significant)
30
+ # but need to confirm this. yes, we support Linux AND Windows.
31
+
32
+ ENV['HOME'] = "/root" unless ENV['HOME'] # Needed by package installer
33
+
34
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gem_dependencies'))
35
+
36
+ $:.push(File.join(File.dirname(__FILE__), '..', 'scripts'))
37
+ require 'agent_controller'
38
+
39
+ RightScale::RightLinkAgentController.run
data/bin/rs_connect ADDED
@@ -0,0 +1,33 @@
1
+ # Copyright (c) 2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ # rs_connect --help for usage information
23
+ #
24
+ # See scripts/server_importer.rb for additional information.
25
+
26
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gem_dependencies'))
27
+
28
+ $:.push(File.join(File.dirname(__FILE__), '..', 'scripts'))
29
+ require 'server_importer'
30
+
31
+ manager = RightScale::ServerImporter.new
32
+ options = manager.parse_args
33
+ manager.run(options)
data/bin/rs_log_level ADDED
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2009-2011 RightScale Inc
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ # rs_log_level --help for usage information
23
+ #
24
+ # See lib/log_level_manager.rb for additional information.
25
+
26
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'gem_dependencies'))
27
+
28
+ $:.push(File.join(File.dirname(__FILE__), '..', 'scripts'))
29
+ require 'log_level_manager'
30
+
31
+ RightScale::RightLinkLogLevelManager::run