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,88 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'socket'
24
+ require 'right_agent/actors/agent_manager'
25
+
26
+ # Extend generic agent manager for fault handling
27
+ AgentManager.class_eval do
28
+
29
+ include RightScale::Actor
30
+ include RightScale::OperationResultHelper
31
+
32
+ on_exception { |_, _, _| }
33
+
34
+ expose :record_fault, :reenroll
35
+
36
+ # Process fault (i.e. mapper failed to decrypt one of our packets)
37
+ # Vote for re-enrollment
38
+ #
39
+ # === Return
40
+ # (RightScale::OperationResult):: Always returns success
41
+ def record_fault(_)
42
+ RightScale::ReenrollManager.vote
43
+ success_result
44
+ end
45
+
46
+ # Force agent to reenroll now
47
+ #
48
+ # === Return
49
+ # (RightScale::OperationResult):: Always returns success
50
+ def reenroll(_)
51
+ RightScale::ReenrollManager.reenroll
52
+ success_result
53
+ end
54
+
55
+ # Process exception raised by handling of packet
56
+ # If it's a serialization error and the packet has a valid signature, vote for re-enroll
57
+ #
58
+ # === Parameters
59
+ # e(Exception):: Exception to be analyzed
60
+ # msg(String):: Serialized message that triggered error
61
+ #
62
+ # === Return
63
+ # true:: Always return true
64
+ def self.process_exception(e, msg)
65
+ if e.is_a?(RightScale::Serializer::SerializationError)
66
+ begin
67
+ serializer = RightScale::Serializer.new
68
+ data = serializer.load(msg)
69
+ sig = RightScale::Signature.from_data(data['signature'])
70
+ @cert ||= RightScale::Certificate.load(RightScale::AgentConfig.certs_file('mapper.cert'))
71
+ RightScale::ReenrollManager.vote if sig.match?(@cert)
72
+ rescue Exception => _
73
+ RightScale::Log.error("Failed processing serialization error", e)
74
+ end
75
+ end
76
+ true
77
+ end
78
+
79
+ # Process request to restart agent by voting to reenroll
80
+ #
81
+ # === Return
82
+ # true:: Always return true
83
+ def self.process_restart
84
+ RightScale::ReenrollManager.vote
85
+ true
86
+ end
87
+
88
+ end
@@ -0,0 +1,321 @@
1
+ #
2
+ # Copyright (c) 2009-2012 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ class InstanceScheduler
24
+
25
+ include RightScale::Actor
26
+ include RightScale::OperationResultHelper
27
+
28
+ expose :schedule_bundle, :execute, :schedule_decommission
29
+
30
+ SHUTDOWN_DELAY = 180 # Number of seconds to wait for decommission scripts to finish before forcing shutdown
31
+
32
+ # Setup signal traps for running decommission scripts
33
+ # Start worker thread for processing executable bundles
34
+ #
35
+ # === Parameters
36
+ # agent(RightScale::Agent):: Host agent
37
+ def initialize(agent)
38
+ @agent = agent
39
+ @agent_identity = agent.identity
40
+
41
+ # invoke the bundles queue factory method as an assist to testing.
42
+ @bundle_queue_closed_callback = nil
43
+ @bundle_queue = self.class.create_bundle_queue { @bundle_queue_closed_callback.call }
44
+
45
+ # Wait until instance setup actor has initialized the instance state
46
+ # We need to wait until after the InstanceSetup actor has run its
47
+ # bundle in the Chef thread before we can use it
48
+ EM.next_tick do
49
+ if RightScale::InstanceState.value != 'booting'
50
+ @bundle_queue.activate
51
+ else
52
+ RightScale::InstanceState.observe { |s| @bundle_queue.activate if s != 'booting' }
53
+ end
54
+ end
55
+ end
56
+
57
+ # Schedule given script bundle so it's run as soon as possible
58
+ #
59
+ # === Parameter
60
+ # bundle(RightScale::ExecutableBundle):: Bundle to be scheduled
61
+ #
62
+ # === Return
63
+ # res(RightScale::OperationResult):: Always returns success
64
+ def schedule_bundle(bundle)
65
+ unless bundle.executables.empty?
66
+ if bundle.respond_to?(:runlist_policy) && bundle.runlist_policy && bundle.runlist_policy.policy_name
67
+ if RightScale::PolicyManager.registered?(bundle)
68
+ policy_audit = RightScale::PolicyManager.get_audit(bundle)
69
+ queue_bundle(bundle, policy_audit)
70
+ else
71
+ RightScale::PolicyManager.register(bundle) do |b, policy_audit|
72
+ queue_bundle(b, policy_audit)
73
+ end
74
+ return success_result
75
+ end
76
+ else
77
+ audit = RightScale::AuditProxy.new(bundle.audit_id)
78
+ queue_bundle(bundle, audit)
79
+ end
80
+ end
81
+ res = success_result
82
+ end
83
+
84
+ def queue_bundle(bundle, audit)
85
+ thread_name = get_thread_name_from_bundle(bundle)
86
+ if thread_name == RightScale::AgentConfig.default_thread_name
87
+ on_thread = ''
88
+ else
89
+ on_thread = " on thread #{thread_name}"
90
+ end
91
+
92
+ if @bundle_queue.busy?
93
+ audit.update_status("Enqueueing #{bundle.to_s} for execution#{on_thread}")
94
+ else
95
+ audit.update_status("Scheduling execution of #{bundle.to_s}#{on_thread}")
96
+ end
97
+
98
+ context = RightScale::OperationContext.new(bundle, audit)
99
+ @bundle_queue.push(context)
100
+ end
101
+
102
+ # FIX: thread_name should never be nil from the core in future, but
103
+ # temporarily we must supply the default thread_name before if nil. in
104
+ # future we should fail execution when thread_name is reliably present and
105
+ # for any reason does not match ::RightScale::AgentConfig.valid_thread_name
106
+ # see also ExecutableSequenceProxy#initialize
107
+ #
108
+ # === Parameters
109
+ # bundle(ExecutableBundle):: An executable bundle
110
+ #
111
+ # === Return
112
+ # result(String):: Thread name of this bundle
113
+ def get_thread_name_from_bundle(bundle)
114
+ thread_name = nil
115
+ thread_name = bundle.runlist_policy.thread_name if bundle.respond_to?(:runlist_policy) && bundle.runlist_policy
116
+ RightScale::Log.warn("Encountered a nil thread name unexpectedly, defaulting to '#{RightScale::AgentConfig.default_thread_name}'") unless thread_name
117
+ thread_name ||= RightScale::AgentConfig.default_thread_name
118
+ unless thread_name =~ RightScale::AgentConfig.valid_thread_name
119
+ raise ArgumentError, "Invalid thread name #{thread_name.inspect}"
120
+ end
121
+ thread_name
122
+ end
123
+
124
+ # Schedules a shutdown by appending it to the bundles queue.
125
+ #
126
+ # === Return
127
+ # always true
128
+ def schedule_shutdown
129
+ @bundle_queue.push(RightScale::BundleQueue::SHUTDOWN_BUNDLE)
130
+ true
131
+ end
132
+
133
+ # Ask agent to execute given recipe or RightScript
134
+ # Agent must forward request to core agent which will in turn run schedule_bundle on this agent
135
+ #
136
+ # === Parameters
137
+ # options[:recipe](String):: Recipe name
138
+ # options[:recipe_id](Integer):: Recipe id
139
+ # options[:right_script](String):: RightScript name
140
+ # options[:right_script_id](Integer):: RightScript id
141
+ # options[:json](Hash):: Serialized hash of attributes to be used when running recipe
142
+ # options[:thread](String):: Thread name (default is 'default')
143
+ # options[:arguments](Hash):: RightScript inputs hash
144
+ #
145
+ # === Return
146
+ # true:: Always return true
147
+ def execute(options)
148
+ payload = options = RightScale::SerializationHelper.symbolize_keys(options)
149
+ payload[:agent_identity] = @agent_identity
150
+
151
+ forwarder = lambda do |type|
152
+ send_retryable_request("/forwarder/schedule_#{type}", payload) do |r|
153
+ r = result_from(r)
154
+ RightScale::Log.error("Failed executing #{type} for #{payload.inspect}", r.content) unless r.success?
155
+ end
156
+ end
157
+
158
+ if options[:recipe] || options[:recipe_id]
159
+ forwarder.call("recipe")
160
+ elsif options[:right_script] || options[:right_script_id]
161
+ forwarder.call("right_script")
162
+ else
163
+ RightScale::Log.error("Unrecognized execute request: #{options.inspect}")
164
+ return true
165
+ end
166
+ true
167
+ end
168
+
169
+ # Schedule decommission, returns an error if instance is already decommissioning
170
+ #
171
+ # === Parameter
172
+ # options[:bundle](RightScale::ExecutableBundle):: Decommission bundle
173
+ # options[:user_id](Integer):: User id which requested decommission
174
+ # options[:skip_db_update](FalseClass|TrueClass):: Whether to requery instance state (false)
175
+ # options[:kind](String):: 'terminate', 'stop' or 'reboot'
176
+ #
177
+ # === Return
178
+ # (RightScale::OperationResult):: Status value, either success or error with message
179
+ def schedule_decommission(options)
180
+ case RightScale::InstanceState.value
181
+ when 'decommissioning', 'decommissioned'
182
+ return error_result('Instance is already decommissioning')
183
+ end
184
+ options = RightScale::SerializationHelper.symbolize_keys(options)
185
+ bundle = options[:bundle]
186
+ decommission_type = options[:kind]
187
+ audit = RightScale::AuditProxy.new(bundle.audit_id)
188
+
189
+ # see note below for reason why decommission_type would be nil.
190
+ context = RightScale::OperationContext.new(
191
+ bundle, audit,
192
+ :decommission_type => decommission_type || 'unknown')
193
+
194
+ # This is the tricky bit: only set a post decommission callback if there wasn't one already set
195
+ # by 'run_decommission'. This default callback will shutdown the instance for soft-termination.
196
+ # The callback set by 'run_decommission' can do other things before calling 'terminate' manually.
197
+ # 'terminate' will *not* shutdown the machine. This is so that when running the decommission
198
+ # sequence as part of a non-soft termination we don't call shutdown.
199
+ unless @bundle_queue_closed_callback
200
+ @shutdown_timeout = EM::Timer.new(SHUTDOWN_DELAY) do
201
+ @shutdown_timeout = nil
202
+ msg = "Failed to decommission in less than #{SHUTDOWN_DELAY / 60} minutes, forcing shutdown"
203
+ audit.append_error(msg, :category => RightScale::EventCategories::CATEGORY_ERROR)
204
+ RightScale::InstanceState.value = 'decommissioned'
205
+ RightScale::InstanceState.shutdown(options[:user_id], options[:skip_db_update], decommission_type)
206
+ end
207
+ @bundle_queue_closed_callback = make_decommission_callback do
208
+ @shutdown_timeout.cancel if @shutdown_timeout
209
+ @shutdown_timeout = nil
210
+ RightScale::InstanceState.shutdown(options[:user_id], options[:skip_db_update], decommission_type)
211
+ end
212
+ end
213
+
214
+ @bundle_queue.clear # Cancel any pending bundle
215
+ unless bundle.executables.empty?
216
+ audit.update_status("Scheduling execution of #{bundle.to_s} for decommission")
217
+ @bundle_queue.push(context)
218
+ end
219
+ @bundle_queue.close
220
+
221
+ # transition state to 'decommissioning' (by setting decommissioning_type if given)
222
+ #
223
+ # note that decommission_type can be nil in case where a script or user
224
+ # shuts down the instance manually (without using rs_shutdown, etc.).
225
+ # more specifically, it happens when "rnac --decommission" is invoked
226
+ # either directly or indirectly (on Linux by runlevel 0|6 script).
227
+ if decommission_type
228
+ RightScale::InstanceState.decommission_type = decommission_type
229
+ else
230
+ RightScale::InstanceState.value = 'decommissioning'
231
+ end
232
+ success_result
233
+ end
234
+
235
+ # Schedule decommission and call given block back once decommission bundle has run
236
+ # Note: Overrides existing post decommission callback if there was one
237
+ # This is so that if the instance is being hard-terminated after soft-termination has started
238
+ # then we won't try to tell the core agent to terminate us again once decommission is done
239
+ #
240
+ # === Block
241
+ # Block to yield once decommission is done
242
+ #
243
+ # === Return
244
+ # true:: Aways return true
245
+ def run_decommission(&callback)
246
+ if RightScale::InstanceState.value == 'decommissioned'
247
+ # We are already decommissioned, just call the post decommission callback
248
+ callback.call if callback
249
+ else
250
+ # set (or override if already decommissioning) bundle queue closed callback.
251
+ @bundle_queue_closed_callback = make_decommission_callback(&callback)
252
+ if RightScale::InstanceState.value != 'decommissioning'
253
+ # Trigger decommission
254
+ send_retryable_request('/booter/get_decommission_bundle', {:agent_identity => @agent_identity}) do |r|
255
+ res = result_from(r)
256
+ if res.success?
257
+ schedule_decommission(:bundle => res.content)
258
+ else
259
+ RightScale::Log.debug("Failed to retrieve decommission bundle: #{res.content}")
260
+ end
261
+ end
262
+ end
263
+ end
264
+ true
265
+ end
266
+
267
+ # Terminate self immediately, abandoning any executing bundles.
268
+ # Note: Will *not* run the decommission scripts; call run_decommission (which
269
+ # yields when fully decommissioned) if you need to decommission before
270
+ # terminating agent.
271
+ #
272
+ # === Return
273
+ # true: always true
274
+ def terminate
275
+ # close must abandon any executing bundles and yield in timely fashion.
276
+ if @bundle_queue.active?
277
+ # set (or override if already decommissioning) bundle queue closed
278
+ # callback. we intentionally abandon any decommission bundle if an
279
+ # explicit terminate request is received (so calling code should wait for
280
+ # decommission to finish before calling terminate).
281
+ @bundle_queue_closed_callback = lambda { inner_terminate }
282
+ @bundle_queue.clear
283
+ @bundle_queue.close
284
+ else
285
+ inner_terminate
286
+ end
287
+ true
288
+ end
289
+
290
+ protected
291
+
292
+ # Factory method for a new bundles queue.
293
+ def self.create_bundle_queue(&block)
294
+ return RightScale::MultiThreadBundleQueue.new(&block)
295
+ end
296
+
297
+ # Prefixes the transition to 'decommissioned' state before callback.
298
+ #
299
+ # === Block
300
+ # yielded after state change
301
+ def make_decommission_callback
302
+ return lambda do
303
+ RightScale::InstanceState.value = 'decommissioned'
304
+ yield
305
+ end
306
+ end
307
+
308
+ # Called internally when it is safe to terminate agent.
309
+ #
310
+ # === Return
311
+ # true: always true
312
+ def inner_terminate
313
+ # stop listening.
314
+ RightScale::CommandRunner.stop
315
+
316
+ # Delay terminate a bit to give reply a chance to be sent
317
+ EM.next_tick { @agent.terminate }
318
+ true
319
+ end
320
+
321
+ end # InstanceScheduler
@@ -0,0 +1,64 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ class InstanceServices
24
+
25
+ include RightScale::Actor
26
+ include RightScale::OperationResultHelper
27
+
28
+ expose :update_login_policy
29
+
30
+ def initialize(agent_identity)
31
+ @agent_identity = agent_identity
32
+ end
33
+
34
+ # Always return success, used for troubleshooting
35
+ #
36
+ # == Parameters:
37
+ # @param [RightScale::LoginPolicy] new login policy to update the instance with
38
+ #
39
+ # == Returns:
40
+ # @return [RightScale::OperationResult] Always returns success
41
+ #
42
+ def update_login_policy(new_policy)
43
+ status = nil
44
+
45
+ RightScale::AuditProxy.create(@agent_identity, 'Updating managed login policy') do |audit|
46
+ begin
47
+ RightScale::LoginManager.instance.update_policy(new_policy, @agent_identity) do |audit_content|
48
+ if audit_content
49
+ audit.create_new_section('Managed login policy updated', :category => RightScale::EventCategories::CATEGORY_SECURITY)
50
+ audit.append_info(audit_content)
51
+ end
52
+ end
53
+ status = success_result
54
+ rescue Exception => e
55
+ audit.create_new_section('Failed to update managed login policy', :category => RightScale::EventCategories::CATEGORY_SECURITY)
56
+ audit.append_error("Error applying login policy: #{e.message}", :category => RightScale::EventCategories::CATEGORY_ERROR)
57
+ RightScale::Log.error('Failed to update managed login policy', e, :trace)
58
+ status = error_result("#{e.class.name}: #{e.message}")
59
+ end
60
+ end
61
+
62
+ status
63
+ end
64
+ end