right_link 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/actors/agent_manager.rb +88 -0
- data/actors/instance_scheduler.rb +321 -0
- data/actors/instance_services.rb +64 -0
- data/actors/instance_setup.rb +567 -0
- data/bin/cloud +25 -0
- data/bin/cook_runner +44 -0
- data/bin/deploy +120 -0
- data/bin/enroll +385 -0
- data/bin/rad +32 -0
- data/bin/rchk +29 -0
- data/bin/rnac +39 -0
- data/bin/rs_connect +33 -0
- data/bin/rs_log_level +31 -0
- data/bin/rs_ohai +28 -0
- data/bin/rs_reenroll +31 -0
- data/bin/rs_run_recipe +34 -0
- data/bin/rs_run_right_script +34 -0
- data/bin/rs_shutdown +33 -0
- data/bin/rs_tag +33 -0
- data/bin/rs_thunk +33 -0
- data/bin/rstat +31 -0
- data/bin/system +16 -0
- data/ext/Rakefile +18 -0
- data/init/config.yml +5 -0
- data/init/init.rb +79 -0
- data/lib/chef/ohai_setup.rb +51 -0
- data/lib/chef/plugins/cloud.rb +91 -0
- data/lib/chef/plugins/cloudstack.rb +23 -0
- data/lib/chef/plugins/ec2.rb +23 -0
- data/lib/chef/plugins/linux/block_device2.rb +24 -0
- data/lib/chef/plugins/rackspace.rb +23 -0
- data/lib/chef/plugins/rightscale.rb +125 -0
- data/lib/chef/plugins/windows/network.rb +114 -0
- data/lib/chef/plugins.rb +74 -0
- data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
- data/lib/chef/providers/dns_resource.rb +100 -0
- data/lib/chef/providers/executable_schedule_provider.rb +70 -0
- data/lib/chef/providers/executable_schedule_resource.rb +144 -0
- data/lib/chef/providers/remote_recipe_provider.rb +86 -0
- data/lib/chef/providers/remote_recipe_resource.rb +101 -0
- data/lib/chef/providers/right_link_tag_provider.rb +73 -0
- data/lib/chef/providers/right_link_tag_resource.rb +59 -0
- data/lib/chef/providers/right_script_provider.rb +190 -0
- data/lib/chef/providers/right_script_resource.rb +113 -0
- data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
- data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
- data/lib/chef/providers/server_collection_provider.rb +66 -0
- data/lib/chef/providers/server_collection_resource.rb +93 -0
- data/lib/chef/providers/windows/powershell_provider.rb +151 -0
- data/lib/chef/providers/windows/powershell_resource.rb +111 -0
- data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
- data/lib/chef/right_providers.rb +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
- data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
- data/lib/chef/windows/chef_node_server.rb +463 -0
- data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
- data/lib/chef/windows/pipe_server.rb +283 -0
- data/lib/chef/windows/powershell_host.rb +285 -0
- data/lib/chef/windows/powershell_pipe_server.rb +136 -0
- data/lib/chef/windows/powershell_provider_base.rb +92 -0
- data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
- data/lib/clouds/cloud.rb +557 -0
- data/lib/clouds/cloud_factory.rb +250 -0
- data/lib/clouds/cloud_utilities.rb +244 -0
- data/lib/clouds/clouds/azure.rb +106 -0
- data/lib/clouds/clouds/cloudstack.rb +114 -0
- data/lib/clouds/clouds/ec2.rb +113 -0
- data/lib/clouds/clouds/eucalyptus.rb +46 -0
- data/lib/clouds/clouds/google.rb +102 -0
- data/lib/clouds/clouds/none.rb +76 -0
- data/lib/clouds/clouds/openstack.rb +30 -0
- data/lib/clouds/clouds/rackspace-ng.rb +54 -0
- data/lib/clouds/clouds/rackspace.rb +78 -0
- data/lib/clouds/clouds/softlayer.rb +91 -0
- data/lib/clouds/metadata_formatter.rb +108 -0
- data/lib/clouds/metadata_provider.rb +128 -0
- data/lib/clouds/metadata_source.rb +87 -0
- data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
- data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
- data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
- data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
- data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
- data/lib/clouds/metadata_tree_climber.rb +144 -0
- data/lib/clouds/metadata_writer.rb +155 -0
- data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
- data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
- data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
- data/lib/clouds/register_clouds.rb +34 -0
- data/lib/clouds.rb +32 -0
- data/lib/gem_dependencies.rb +83 -0
- data/lib/git_hooks/commit-msg.rb +7 -0
- data/lib/instance/agent_config.rb +168 -0
- data/lib/instance/agent_watcher.rb +233 -0
- data/lib/instance/audit_cook_stub.rb +104 -0
- data/lib/instance/audit_proxy.rb +247 -0
- data/lib/instance/bundle_queue.rb +104 -0
- data/lib/instance/cook/agent_connection.rb +109 -0
- data/lib/instance/cook/audit_logger.rb +165 -0
- data/lib/instance/cook/audit_stub.rb +142 -0
- data/lib/instance/cook/ca-bundle.crt +2794 -0
- data/lib/instance/cook/chef_state.rb +211 -0
- data/lib/instance/cook/cook.rb +306 -0
- data/lib/instance/cook/cook_state.rb +298 -0
- data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
- data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
- data/lib/instance/cook/executable_sequence.rb +765 -0
- data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
- data/lib/instance/cook/repose_downloader.rb +349 -0
- data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
- data/lib/instance/cook.rb +41 -0
- data/lib/instance/downloader.rb +208 -0
- data/lib/instance/duplicable.rb +67 -0
- data/lib/instance/exceptions.rb +49 -0
- data/lib/instance/executable_sequence_proxy.rb +278 -0
- data/lib/instance/instance_commands.rb +577 -0
- data/lib/instance/instance_state.rb +633 -0
- data/lib/instance/json_utilities.rb +102 -0
- data/lib/instance/login_manager.rb +533 -0
- data/lib/instance/login_user_manager.rb +522 -0
- data/lib/instance/message_encoder.rb +118 -0
- data/lib/instance/multi_thread_bundle_queue.rb +232 -0
- data/lib/instance/operation_context.rb +60 -0
- data/lib/instance/options_bag.rb +65 -0
- data/lib/instance/payload_formatter.rb +46 -0
- data/lib/instance/policy.rb +53 -0
- data/lib/instance/policy_audit.rb +100 -0
- data/lib/instance/policy_manager.rb +146 -0
- data/lib/instance/reenroll_manager.rb +104 -0
- data/lib/instance/right_scripts_cookbook.rb +181 -0
- data/lib/instance/shutdown_request.rb +221 -0
- data/lib/instance/single_thread_bundle_queue.rb +189 -0
- data/lib/instance/volume_management.rb +450 -0
- data/lib/instance.rb +50 -0
- data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
- data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
- data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
- data/lib/repo_conf_generators/rightscale_key.pub +17 -0
- data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
- data/lib/repo_conf_generators.rb +30 -0
- data/lib/run_shell.rb +28 -0
- data/scripts/agent_checker.rb +571 -0
- data/scripts/agent_controller.rb +247 -0
- data/scripts/agent_deployer.rb +148 -0
- data/scripts/bundle_runner.rb +336 -0
- data/scripts/cloud_controller.rb +176 -0
- data/scripts/log_level_manager.rb +142 -0
- data/scripts/ohai_runner.rb +33 -0
- data/scripts/reenroller.rb +193 -0
- data/scripts/server_importer.rb +293 -0
- data/scripts/shutdown_client.rb +183 -0
- data/scripts/system_configurator.rb +367 -0
- data/scripts/tagger.rb +381 -0
- data/scripts/thunker.rb +356 -0
- metadata +418 -0
@@ -0,0 +1,83 @@
|
|
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
|
+
# RVM pollutes the process environment with garbage that prevents us from activating sandboxed
|
23
|
+
# RubyGems correctly. Unpollute the environment so our built-in RubyGems can setup the variables
|
24
|
+
# appropriately for our own usage (and for installation of gems into the sandbox!)
|
25
|
+
['GEM_HOME', 'GEM_PATH', 'IRBRC', 'MY_RUBY_HOME'].each { |key| ENV.delete(key) }
|
26
|
+
|
27
|
+
require 'rubygems'
|
28
|
+
|
29
|
+
# Note: can't use File#normalize_path (for Windows safety) yet because it's
|
30
|
+
# defined by right_agent and gems haven't been activated yet.
|
31
|
+
basedir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
32
|
+
|
33
|
+
Dir.chdir(basedir) do
|
34
|
+
if File.exist?('Gemfile')
|
35
|
+
# Development mode: activate Bundler gem, then let it setup our RubyGems
|
36
|
+
# environment for us -- but don't have it auto-require any gem files; we
|
37
|
+
# will do that ourselves.
|
38
|
+
require 'bundler'
|
39
|
+
Bundler.setup
|
40
|
+
else
|
41
|
+
# Release mode: use 'bare' RubyGems; assume that all gems were installed
|
42
|
+
# as system gems. Nothing to do here...
|
43
|
+
gem 'right_link'
|
44
|
+
|
45
|
+
gem 'eventmachine'
|
46
|
+
|
47
|
+
gem 'right_support'
|
48
|
+
gem 'right_amqp'
|
49
|
+
gem 'right_agent'
|
50
|
+
gem 'right_popen'
|
51
|
+
gem 'right_http_connection'
|
52
|
+
gem 'right_scraper'
|
53
|
+
|
54
|
+
gem 'ohai'
|
55
|
+
gem 'chef'
|
56
|
+
|
57
|
+
# Note: can't use RightScale::Platform because gem sources aren't loaded
|
58
|
+
if RUBY_PLATFORM =~ /mswin|mingw/
|
59
|
+
gem 'win32-api'
|
60
|
+
gem 'windows-api'
|
61
|
+
gem 'windows-pr'
|
62
|
+
gem 'win32-dir'
|
63
|
+
gem 'win32-eventlog'
|
64
|
+
gem 'ruby-wmi'
|
65
|
+
gem 'win32-process'
|
66
|
+
gem 'win32-pipe'
|
67
|
+
gem 'win32-open3'
|
68
|
+
gem 'win32-service'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Make sure gem bin directories appear at the end of the PATH so our wrapper
|
74
|
+
# scripts (e.g. those installed to /usr/bin) get top billing *iff* a bin dir
|
75
|
+
# already appears on the PATH. Notice we choose regexp patterns that work under
|
76
|
+
# both Linux and Windows.
|
77
|
+
sep = (RUBY_PLATFORM =~ /mswin|mingw|dos/) ? ';' : ':'
|
78
|
+
version = RUBY_VERSION.split('.')[0..1].join('.')
|
79
|
+
subdir = /(ruby|gems)[\\\/]#{version}[\\\/]bin/
|
80
|
+
paths = ENV['PATH'].split(sep)
|
81
|
+
gem_bin = paths.select { |p| p =~ subdir }
|
82
|
+
paths.delete_if { |p| p =~ subdir }
|
83
|
+
ENV['PATH'] = (paths + gem_bin).join(sep)
|
@@ -0,0 +1,168 @@
|
|
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 'rbconfig'
|
24
|
+
|
25
|
+
module RightScale
|
26
|
+
|
27
|
+
# Extend AgentConfig for instance agents
|
28
|
+
AgentConfig.module_eval do
|
29
|
+
|
30
|
+
# Path to RightScale files in parent directory of right_link
|
31
|
+
def self.parent_dir
|
32
|
+
File.dirname(File.normalize_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'right_link')))
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Array] an appropriate sequence of root directories for configuring the RightLink agent
|
36
|
+
def self.right_link_root_dirs
|
37
|
+
# RightLink certs are written at enrollment time, and live in the
|
38
|
+
# 'certs' subdir of the RightLink agent state dir.
|
39
|
+
os_root_dir = File.join(AgentConfig.agent_state_dir)
|
40
|
+
|
41
|
+
# RightLink actors and the agent init directory are both packaged into the RightLink gem,
|
42
|
+
# as subdirectories of the gem base directory (siblings of 'lib' and 'bin' directories).
|
43
|
+
gem_root_dir = Gem.loaded_specs['right_link'].full_gem_path
|
44
|
+
|
45
|
+
[os_root_dir, gem_root_dir]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Path to directory containing persistent RightLink agent state
|
49
|
+
def self.agent_state_dir
|
50
|
+
RightScale::Platform.filesystem.right_link_dynamic_state_dir
|
51
|
+
end
|
52
|
+
|
53
|
+
# Path to the file that contains the name of the cloud for this instance
|
54
|
+
def self.cloud_file_path
|
55
|
+
File.normalize_path(File.join(
|
56
|
+
RightScale::Platform.filesystem.right_scale_static_state_dir,
|
57
|
+
'cloud'))
|
58
|
+
end
|
59
|
+
|
60
|
+
# Path to directory containing transient cloud-related state (metadata, userdata, etc)
|
61
|
+
def self.cloud_state_dir
|
62
|
+
@cloud_state_dir ||= File.join(RightScale::Platform.filesystem.spool_dir, 'cloud')
|
63
|
+
end
|
64
|
+
|
65
|
+
# Set path to directory containing transient cloud-related state (metadata, userdata, etc)
|
66
|
+
def self.cloud_state_dir=(dir)
|
67
|
+
@cloud_state_dir = dir
|
68
|
+
end
|
69
|
+
|
70
|
+
# Path to directory for caching instance data
|
71
|
+
def self.cache_dir
|
72
|
+
@cache_dir ||= File.join(RightScale::Platform.filesystem.cache_dir, 'rightscale')
|
73
|
+
end
|
74
|
+
|
75
|
+
# Set path to directory for caching instance data
|
76
|
+
def self.cache_dir=(dir)
|
77
|
+
@cache_dir = dir
|
78
|
+
end
|
79
|
+
|
80
|
+
# Path to directory for Ruby source code, e.g. cookbooks
|
81
|
+
def self.source_code_dir
|
82
|
+
@source_code_dir ||= File.join(RightScale::Platform.filesystem.source_code_dir, 'rightscale')
|
83
|
+
end
|
84
|
+
|
85
|
+
# Set path to directory for Ruby source code, e.g. cookbooks
|
86
|
+
def self.source_code_dir=(dir)
|
87
|
+
@source_code_dir = dir
|
88
|
+
end
|
89
|
+
|
90
|
+
# Path to downloaded cookbooks directory
|
91
|
+
def self.cookbook_download_dir
|
92
|
+
@cookbook_download_dir ||= File.join(cache_dir, 'cookbooks')
|
93
|
+
end
|
94
|
+
|
95
|
+
# Path to SCM repository checkouts that contain development cookbooks
|
96
|
+
def self.dev_cookbook_checkout_dir
|
97
|
+
@dev_cookbook_dir ||= File.join(source_code_dir, 'cookbooks')
|
98
|
+
end
|
99
|
+
|
100
|
+
# Path to RightScript recipes cookbook directory
|
101
|
+
def self.right_scripts_repo_dir
|
102
|
+
@right_scripts_repo_dir ||= File.join(cache_dir, 'right_scripts')
|
103
|
+
end
|
104
|
+
|
105
|
+
# Maximum number of times agent should retry installing packages
|
106
|
+
def self.max_packages_install_retries
|
107
|
+
3
|
108
|
+
end
|
109
|
+
|
110
|
+
# Path to directory for sandbox if it exists
|
111
|
+
def self.ruby_dir
|
112
|
+
( ENV['RS_RUBY_EXE'] && File.dirname(ENV['RS_RUBY_EXE']) ) ||
|
113
|
+
Config::CONFIG["bindir"]
|
114
|
+
end
|
115
|
+
|
116
|
+
# Ruby command
|
117
|
+
def self.ruby_cmd
|
118
|
+
# Allow test environment to specify a non-program files location for tools
|
119
|
+
ENV['RS_RUBY_EXE'] ||
|
120
|
+
File.join( ruby_dir,
|
121
|
+
Config::CONFIG["RUBY_INSTALL_NAME"] + Config::CONFIG["EXEEXT"] )
|
122
|
+
end
|
123
|
+
|
124
|
+
# Sandbox gem command
|
125
|
+
def self.gem_cmd
|
126
|
+
if RightScale::Platform.windows?
|
127
|
+
# Allow test environment to specify a non-program files location for tools
|
128
|
+
if ENV['RS_GEM']
|
129
|
+
ENV['RS_GEM']
|
130
|
+
elsif dir = ruby_dir
|
131
|
+
"\"#{ruby_cmd}\" \"#{File.join(dir, 'gem.exe')}\""
|
132
|
+
else
|
133
|
+
'gem'
|
134
|
+
end
|
135
|
+
else
|
136
|
+
if dir = ruby_dir
|
137
|
+
File.join(dir, 'gem')
|
138
|
+
else
|
139
|
+
# Development setup
|
140
|
+
`which gem`.chomp
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Sandbox git command
|
146
|
+
def self.git_cmd
|
147
|
+
if RightScale::Platform.windows?
|
148
|
+
# Allow test environment to specify a non-program files location for tools
|
149
|
+
if ENV['RS_GIT_EXE']
|
150
|
+
ENV['RS_GIT_EXE']
|
151
|
+
elsif dir = ruby_dir
|
152
|
+
File.normalize_path(File.join(dir, '..', '..', 'bin', 'windows', 'git.cmd'))
|
153
|
+
else
|
154
|
+
'git'
|
155
|
+
end
|
156
|
+
else
|
157
|
+
if dir = ruby_dir
|
158
|
+
File.join(dir, 'git')
|
159
|
+
else
|
160
|
+
# Development setup
|
161
|
+
`which git`.chomp
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end # AgentConfig
|
167
|
+
|
168
|
+
end # RightScale
|
@@ -0,0 +1,233 @@
|
|
1
|
+
# === Synopsis:
|
2
|
+
# RightScale Agent Watcher
|
3
|
+
#
|
4
|
+
# Agent monitoring intelligence. Will watch a given list of agents for
|
5
|
+
# unexpected termination and react accordingly. This can be either simply
|
6
|
+
# logging to a given IO stream, restarting the agent or yielding to any
|
7
|
+
# arbitrary block passed in during initialization.
|
8
|
+
#
|
9
|
+
# Copyright (c) 2013 RightScale Inc
|
10
|
+
#
|
11
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
12
|
+
# a copy of this software and associated documentation files (the
|
13
|
+
# "Software"), to deal in the Software without restriction, including
|
14
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
15
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
16
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
17
|
+
# the following conditions:
|
18
|
+
#
|
19
|
+
# The above copyright notice and this permission notice shall be
|
20
|
+
# included in all copies or substantial portions of the Software.
|
21
|
+
#
|
22
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
23
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
24
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
25
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
26
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
27
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
28
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
29
|
+
#
|
30
|
+
|
31
|
+
require 'rubygems'
|
32
|
+
require 'right_agent/pid_file'
|
33
|
+
require 'thread'
|
34
|
+
|
35
|
+
module RightScale
|
36
|
+
|
37
|
+
class AgentWatcher
|
38
|
+
class AlreadyWatched < Exception; end
|
39
|
+
class UnknownAgent < Exception; end
|
40
|
+
|
41
|
+
# Some Time calculation constants
|
42
|
+
# ===
|
43
|
+
SECOND = 1
|
44
|
+
MINUTE = 60 * SECOND
|
45
|
+
HOUR = 60 * MINUTE
|
46
|
+
DAY = 24 * HOUR
|
47
|
+
# ===
|
48
|
+
|
49
|
+
DEFAULT_FREQUENCY_CHECK = 5 * SECOND
|
50
|
+
|
51
|
+
def initialize(logger, pid_dir=nil)
|
52
|
+
@logger = logger
|
53
|
+
@pid_dir = pid_dir
|
54
|
+
@running = false
|
55
|
+
@stopped_list = {}
|
56
|
+
@watched_list = {}
|
57
|
+
@watch_list_lock = Monitor.new
|
58
|
+
end
|
59
|
+
|
60
|
+
def log_info(s)
|
61
|
+
@logger.call("AgentWatcher: #{s}")
|
62
|
+
end
|
63
|
+
|
64
|
+
def kill_agent(identity, signal='SIGKILL')
|
65
|
+
@watch_list_lock.synchronize do
|
66
|
+
raise UnknownAgent("#{identity} is not a known agent.") unless @watched_list.has_key?(identity)
|
67
|
+
agent = @watched_list.delete(identity)
|
68
|
+
Process.kill(signal, agent[:pid].read_pid[:pid])
|
69
|
+
@stopped_list[identity] = agent
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def restart_agent(identity)
|
74
|
+
stop_agent(identity)
|
75
|
+
start_agent(identity)
|
76
|
+
end
|
77
|
+
|
78
|
+
def start_watching()
|
79
|
+
return if @running
|
80
|
+
# This logic is implemented with a priority queue of "next check" times:
|
81
|
+
#
|
82
|
+
# This allows us not to have to start a bunch of timers and do time
|
83
|
+
# alrithmatic which can be tricky when someone goes and changes the date
|
84
|
+
# on the system this code is running.
|
85
|
+
|
86
|
+
# Initialize all agents
|
87
|
+
@watch_list_lock.synchronize {
|
88
|
+
@watched_list.each { |k, v| v[:next_check] = 0 }
|
89
|
+
}
|
90
|
+
|
91
|
+
log_info("Starting the AgentWatcher.")
|
92
|
+
@agent_watcher_thread = Thread.new do
|
93
|
+
@running = true
|
94
|
+
while @running
|
95
|
+
next_check = 0
|
96
|
+
time_start = Time.now
|
97
|
+
|
98
|
+
# TODO: This may need to be refactored into a real priority queue if we
|
99
|
+
# start to have large amounts of agents assigned, rather than incur the
|
100
|
+
# overhead of discovering the next smallest number every iteration. -brs
|
101
|
+
@watch_list_lock.synchronize do
|
102
|
+
# No use doing anything till we have something to work on, I would have
|
103
|
+
# rather used a ConditionVariable here, but they are not compatible with
|
104
|
+
# Monitor objects, and I need reentrance.
|
105
|
+
sleep DEFAULT_FREQUENCY_CHECK until @watched_list.size > 0 or not @running
|
106
|
+
|
107
|
+
# Check all processes in the list with a next check time of zero
|
108
|
+
# replacing the next check time with their frequency.
|
109
|
+
@watched_list.each do |k,v|
|
110
|
+
if v[:next_check] <= 0
|
111
|
+
v[:next_check] = v[:freq]
|
112
|
+
check_agent(k)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Find the lowest next check
|
117
|
+
@watched_list.each do |k,v|
|
118
|
+
next_check = v[:next_check] unless (next_check > 0 and next_check < v[:next_check])
|
119
|
+
end
|
120
|
+
|
121
|
+
# Subtract this from all the elements before we sleep
|
122
|
+
@watched_list.each do |k,v|
|
123
|
+
v[:next_check] -= next_check
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Account for the time it took to check agents and find the next
|
128
|
+
# check time.
|
129
|
+
next_check -= (Time.now - time_start).to_i
|
130
|
+
|
131
|
+
# Sleep for the next check time
|
132
|
+
next_check -= sleep(next_check) while (next_check > 0 and @running)
|
133
|
+
end
|
134
|
+
log_info("Shutting down.")
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def start_agent(identity)
|
139
|
+
@watch_list_lock.synchronize {
|
140
|
+
raise UnknownAgent("#{identity} is not a known stopped agent.") unless @stopped_list.has_key?(identity)
|
141
|
+
agent = @stopped_list.delete(identity)
|
142
|
+
agent[:pid].remove
|
143
|
+
system("#{agent[:exec]} #{agent[:start_opts]}")
|
144
|
+
log_info("Successfully started the #{identity} agent.")
|
145
|
+
# Give us some time to come up before the next check...should be good in
|
146
|
+
# 60 seconds I would think.
|
147
|
+
agent[:next_check] = MINUTE
|
148
|
+
@watched_list[identity] = agent
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def stop_watching()
|
153
|
+
return unless @running
|
154
|
+
log_info("Stopping the AgentWatcher.")
|
155
|
+
@running = false
|
156
|
+
@agent_watcher_thread.terminate
|
157
|
+
@agent_watcher_thread.join
|
158
|
+
@agent_watcher_thread = nil
|
159
|
+
log_info("AgentWatcher Stopped.")
|
160
|
+
end
|
161
|
+
|
162
|
+
def stop_agent(identity)
|
163
|
+
@watch_list_lock.synchronize {
|
164
|
+
raise UnknownAgent("#{identity} is not a known agent.") unless @watched_list.has_key?(identity)
|
165
|
+
agent = @watched_list.delete(identity)
|
166
|
+
if system("#{agent[:exec]} #{agent[:stop_opts]}")
|
167
|
+
log_info("Successfully stopped the #{identity} agent.")
|
168
|
+
agent[:pid].remove
|
169
|
+
end
|
170
|
+
@stopped_list[identity] = agent
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
def watch_agent(identity, exec, start_opts, stop_opts, freq=DEFAULT_FREQUENCY_CHECK)
|
175
|
+
# Make things simple for now and require a resolution of 1 second
|
176
|
+
# for the frequency check.
|
177
|
+
raise BadFrequency.new unless (freq > 1)
|
178
|
+
|
179
|
+
# Protect the watch list from the thread monitoring the agents
|
180
|
+
@watch_list_lock.synchronize {
|
181
|
+
unless @watched_list.has_key?(identity)
|
182
|
+
|
183
|
+
# If we were given a block, use that for state change, otherwise restart
|
184
|
+
action = (block_given? && Proc.new) || Proc.new do |identity, state, mesg|
|
185
|
+
if state == :stopped
|
186
|
+
log_info("#{identity} has stopped, restarting now.")
|
187
|
+
self.start_agent(identity)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
@watched_list[identity] = {
|
192
|
+
:action=>action,
|
193
|
+
:exec=>exec,
|
194
|
+
:start_opts=>start_opts,
|
195
|
+
:stop_opts=>stop_opts,
|
196
|
+
:freq=>freq,
|
197
|
+
:pid=>PidFile.new(identity,@pid_dir),
|
198
|
+
}
|
199
|
+
else
|
200
|
+
raise AlreadyWatched.new("The agent [#{identity}] is already being watched by us.")
|
201
|
+
end
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
205
|
+
private
|
206
|
+
|
207
|
+
def agent_running?(identity)
|
208
|
+
# The check method really tells us if the agent ISN'T running
|
209
|
+
# and throws an exception if it is...poorly named I know
|
210
|
+
@watch_list_lock.synchronize do
|
211
|
+
begin
|
212
|
+
@watched_list[identity][:pid].check
|
213
|
+
false
|
214
|
+
rescue PidFile::AlreadyRunning
|
215
|
+
true
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def check_agent(identity)
|
221
|
+
@watch_list_lock.synchronize do
|
222
|
+
test_agent = agent_running?(identity)
|
223
|
+
unless test_agent
|
224
|
+
agent = @watched_list.delete(identity)
|
225
|
+
@stopped_list[identity] = agent
|
226
|
+
agent[:action].call(identity, :stopped, "The #{identity} agent does not appear to be running!")
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
@@ -0,0 +1,104 @@
|
|
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
|
+
|
24
|
+
module RightScale
|
25
|
+
|
26
|
+
# This class acts as a recipient of audit requests sent by the cook
|
27
|
+
# process.
|
28
|
+
# The audit proxy which will forward the audits to the core should be
|
29
|
+
# initialized before each invocation to cook
|
30
|
+
class AuditCookStub
|
31
|
+
|
32
|
+
include RightSupport::Ruby::EasySingleton
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@auditors = {}
|
36
|
+
@close_callbacks = {}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Sets up the audit proxy that should be used to forward all audit commands.
|
40
|
+
#
|
41
|
+
# === Parameters
|
42
|
+
# thread_name(String):: execution thread name or default
|
43
|
+
# auditor(AuditProxy):: audit proxy
|
44
|
+
def setup_audit_forwarding(thread_name, auditor)
|
45
|
+
@auditors ||= {}
|
46
|
+
@auditors[thread_name] = auditor
|
47
|
+
end
|
48
|
+
|
49
|
+
# Forward audit command received from cook using audit proxy
|
50
|
+
#
|
51
|
+
# === Parameters
|
52
|
+
# kind(Symbol):: Kind of audit, one of :append_info, :append_error, :create_new_section, :update_status and :append_output
|
53
|
+
# text(String):: Audit content
|
54
|
+
# thread_name(String):: thread name for audit or default
|
55
|
+
# options[:category]:: Optional, associated event category, one of RightScale::EventCategories
|
56
|
+
#
|
57
|
+
# === Raise
|
58
|
+
# RuntimeError:: If audit_proxy is not set prior to calling this
|
59
|
+
def forward_audit(kind, text, thread_name, options)
|
60
|
+
auditor = @auditors[thread_name]
|
61
|
+
return unless auditor
|
62
|
+
if kind == :append_output
|
63
|
+
auditor.append_output(text)
|
64
|
+
else
|
65
|
+
auditor.__send__(kind, text, options)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Register listener for when audit proxy is closed/reset
|
70
|
+
# Listener is executable sequence proxy to synchronize betweek
|
71
|
+
# cook process going away and all audits having been processed
|
72
|
+
#
|
73
|
+
# === Parameters
|
74
|
+
# thread_name(String):: execution thread name or default
|
75
|
+
#
|
76
|
+
# === Block
|
77
|
+
# Given block should not take any argument and gets called back when proxy is reset
|
78
|
+
#
|
79
|
+
# === Return
|
80
|
+
# true:: Always return true
|
81
|
+
def on_close(thread_name, &blk)
|
82
|
+
@close_callbacks[thread_name] = blk
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
# Reset proxy object and notify close event listener
|
87
|
+
#
|
88
|
+
# === Parameters
|
89
|
+
# thread_name(String):: execution thread name or default
|
90
|
+
#
|
91
|
+
# === Return
|
92
|
+
# true:: Always return true
|
93
|
+
def close(thread_name)
|
94
|
+
close_callback = @close_callbacks[thread_name]
|
95
|
+
close_callback.call if close_callback
|
96
|
+
true
|
97
|
+
ensure
|
98
|
+
@auditors[thread_name] = nil
|
99
|
+
@close_callbacks[thread_name] = nil
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|