auser-poolparty 1.3.5 → 1.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Rakefile +2 -2
  2. data/VERSION.yml +1 -1
  3. data/bin/cloud-misc +34 -0
  4. data/bin/{poolparty-setup → cloud-setup} +0 -0
  5. data/bin/cloud-ssh +4 -1
  6. data/config/jeweler.rb +4 -3
  7. data/examples/monitored_cloud.rb +1 -1
  8. data/examples/thrift/thrift_example.rb +5 -3
  9. data/examples/vmware.rb +10 -0
  10. data/lib/cloud_providers/cloud_provider_instance.rb +13 -4
  11. data/lib/cloud_providers/connections.rb +1 -1
  12. data/lib/core/file.rb +12 -0
  13. data/lib/dependency_resolvers/base.rb +1 -1
  14. data/lib/dependency_resolvers/chef.rb +7 -5
  15. data/lib/dependency_resolvers/proxy_object.rb +11 -3
  16. data/lib/poolparty.rb +3 -1
  17. data/lib/poolparty/base.rb +1 -2
  18. data/lib/poolparty/cloud.rb +20 -5
  19. data/lib/poolparty/default.rb +1 -0
  20. data/lib/poolparty/plugin.rb +1 -5
  21. data/lib/poolparty/plugins/apache.rb +8 -6
  22. data/lib/poolparty/plugins/collectd.rb +24 -0
  23. data/lib/poolparty/plugins/collectd/templates/collectd.conf.erb +369 -0
  24. data/lib/poolparty/plugins/hermes.rb +89 -0
  25. data/lib/poolparty/pool.rb +26 -3
  26. data/lib/poolparty/resource.rb +12 -11
  27. data/lib/poolparty/resources/line.rb +2 -2
  28. data/lib/poolparty/resources/variable.rb +4 -3
  29. data/lib/proto/command_interface_handler.rb +17 -1
  30. data/lib/proto/gen-py/cloudthrift/CommandInterface.pyc +0 -0
  31. data/lib/proto/gen-py/cloudthrift/__init__.pyc +0 -0
  32. data/lib/proto/gen-py/cloudthrift/constants.pyc +0 -0
  33. data/lib/proto/gen-py/cloudthrift/ttypes.pyc +0 -0
  34. data/lib/proto/gen-py/thrift/Thrift.pyc +0 -0
  35. data/lib/proto/gen-py/thrift/__init__.pyc +0 -0
  36. data/lib/proto/gen-py/thrift/protocol/TBinaryProtocol.pyc +0 -0
  37. data/lib/proto/gen-py/thrift/protocol/TProtocol.pyc +0 -0
  38. data/lib/proto/gen-py/thrift/protocol/__init__.pyc +0 -0
  39. data/lib/proto/gen-py/thrift/transport/TSocket.pyc +0 -0
  40. data/lib/proto/gen-py/thrift/transport/TTransport.pyc +0 -0
  41. data/lib/proto/gen-py/thrift/transport/__init__.pyc +0 -0
  42. data/test/lib/dependency_resolvers/chef_test.rb +92 -100
  43. data/test/lib/poolparty/cloud_test.rb +50 -2
  44. data/test/lib/poolparty/monitor_test.rb +2 -2
  45. data/test/lib/poolparty/resource_test.rb +5 -0
  46. data/test/lib/poolparty/resources/variable_test.rb +33 -10
  47. metadata +11 -4
data/Rakefile CHANGED
@@ -39,8 +39,8 @@ end
39
39
 
40
40
  # Generate documentation
41
41
  Rake::RDocTask.new do |rd|
42
- rd.main = "Readme.txt"
43
- rd.rdoc_files.include("Readme.txt", "lib/**/*.rb")
42
+ rd.main = "README.rdoc"
43
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
44
44
  rd.rdoc_dir = "rdoc"
45
45
  # rd.template = "hanaa"
46
46
  end
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 3
3
- :patch: 5
3
+ :patch: 6
4
4
  :major: 1
data/bin/cloud-misc ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(__FILE__) + "/../lib")
3
+ require "poolparty"
4
+
5
+ require 'git-style-binary/command'
6
+
7
+ GitStyleBinary.command do
8
+ banner <<-EOS
9
+ Usage: #{$0} #{all_options_string}
10
+
11
+ read the code
12
+ EOS
13
+
14
+ short_desc "various cloud development tasks"
15
+
16
+ opt :inst_num, "The number of the instance to run bootstrap on", :type => :int
17
+ opt :force, "Force rebootstrapping (useful for upgrading)", :default => false
18
+
19
+ run do |command|
20
+ @loaded_clouds.each do |cld|
21
+ cld.nodes.each do |node|
22
+
23
+ case command.argv.shift
24
+ when "deploy_hermes"
25
+ hermesdir = File.dirname(__FILE__) + "/../vendor/erlang/hermes"
26
+ release = `#{hermesdir}/scripts/most_recent_release tar.gz`.strip
27
+ node.scp(:source => release, :destination => "/var/poolparty/tmp")
28
+ node.scp(:source => "#{hermesdir}/scripts/target_system", :destination => "/var/poolparty/tmp")
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
File without changes
data/bin/cloud-ssh CHANGED
@@ -13,11 +13,14 @@ EOS
13
13
 
14
14
  short_desc "ssh into an instance of the cloud"
15
15
 
16
+ opt :instance_number, "Ssh into the instance number", :type => :integer, :default => 0
17
+
16
18
  run do |command|
17
19
  cloud = @loaded_clouds.first
18
20
 
19
21
  if !cloud.nodes.empty?
20
- cloud.nodes.first.ssh
22
+ inst = cloud.nodes[command[:instance_number]]
23
+ inst ? inst.ssh : puts("Error: The instance number (#{command[:instance_number]}) is too high for the current number of instances")
21
24
  else
22
25
  puts "No running instances can be found"
23
26
  end
data/config/jeweler.rb CHANGED
@@ -26,11 +26,12 @@ end
26
26
 
27
27
  s.files = (%w(Rakefile README.rdoc License.txt VERSION.yml) + Dir["{config,examples,lib,test,tasks,script,generators,bin,vendor}/**/*"])
28
28
 
29
- s.files.exclude '**/*.beam'
30
- s.files.exclude "**/*/erl_crash.dump"
29
+ s.files.exclude 'vendor/erlang/*'
30
+ s.files.exclude 'examples/thrift/**/*.beam'
31
+ # s.files.exclude "**/*/erl_crash.dump"
31
32
 
32
33
  s.has_rdoc = true
33
- s.extra_rdoc_files = ["README.txt", "License.txt", 'History.txt']
34
+ s.extra_rdoc_files = ["README.rdoc", "License.txt", 'History.txt']
34
35
  s.require_paths = ["lib"]
35
36
  s.rdoc_options = ['--quiet', '--title', 'PoolParty documentation',
36
37
  # "index.html",
@@ -10,7 +10,7 @@ pool "poolparty" do
10
10
  image_id 'emi-39CA160F'
11
11
  end
12
12
 
13
- monitor :cpu do |c|
13
+ monitor :'cpu-idle' do |c|
14
14
  vote_for(:expand) if c > 0.9
15
15
  vote_for(:contract) if c < 0.1
16
16
  end
@@ -3,7 +3,7 @@
3
3
  $:.unshift(File.dirname(__FILE__) + "/../../lib")
4
4
  $:.unshift(File.dirname(__FILE__) + "/../../examples")
5
5
  require "poolparty"
6
- require "simple"
6
+ # require "simple"
7
7
 
8
8
  $:.unshift("#{File.dirname(__FILE__)}/../../lib/proto/gen-rb")
9
9
 
@@ -15,6 +15,7 @@ require "poolparty_types"
15
15
  port = ARGV.pop || 11223
16
16
 
17
17
  transport = Thrift::BufferedTransport.new(Thrift::Socket.new('localhost', port))
18
+ # transport = Thrift::BufferedTransport.new(Thrift::Socket.new('vm', port))
18
19
  protocol = Thrift::BinaryProtocol.new(transport)
19
20
 
20
21
  client = CloudThrift::CommandInterface::Client.new(protocol)
@@ -22,6 +23,7 @@ transport.open()
22
23
 
23
24
  cld = CloudThrift::CloudQuery.new
24
25
  cld.name = 'monitored_app'
26
+ # cld.name = 'vmware'
25
27
 
26
28
  resp = client.run_command(cld, "name", [])
27
29
  puts resp.response
@@ -29,8 +31,8 @@ puts resp.response
29
31
  resp = client.run_command(cld, "maximum_instances", [])
30
32
  puts resp.response
31
33
 
32
- resp = client.run_command(cld, "run_monitor", ["cpu", "0.91"])
34
+ resp = client.run_command(cld, "run_monitor", ["cpu-idle", "0.91"])
33
35
  p resp.response
34
36
 
35
- resp = client.run_command(cld, "run_monitor", ["cpu", "0.01"])
37
+ resp = client.run_command(cld, "run_monitor", ["cpu-idle", "0.01"])
36
38
  p resp.response
data/examples/vmware.rb CHANGED
@@ -10,9 +10,19 @@ pool "poolparty" do
10
10
  image_id "/Users/nmurray/Documents/VMware/Ubuntu-jaunty.vmwarevm/Ubuntu-jaunty.vmx"
11
11
  public_ip "192.168.133.128"
12
12
  end
13
+ has_hermes
13
14
  has_file "/etc/motd", :content => "welcome to your instance"
14
15
 
15
16
  has_convenience_helpers
16
17
  end
17
18
 
18
19
  end
20
+
21
+ # hermes
22
+ # want to be able to run cloud configure to update it
23
+ # but want to be able to pull from locally to configure it
24
+ # submodules?
25
+ # node name
26
+ # install path
27
+ # how to upload the escript target system
28
+ # how to upload the tar.gz of the release
@@ -66,16 +66,16 @@ module CloudProviders
66
66
  bootstrap! unless bootstrapped?
67
67
  callback :before_configure
68
68
  raise StandardError.new("You must pass in a cloud to configure an instance") unless cloud
69
- cloud.compile(self)
69
+ cloud.compile(self)
70
+
70
71
  scp(:source => keypair.full_filepath,
71
72
  :destination => "/etc/poolparty/keys/#{keypair.basename}")
72
- script_file = Provision::Bootstrapper.configure_script(cloud, os)
73
73
 
74
74
  FileUtils.mkdir_p cloud.tmp_path/"etc"/"poolparty" unless File.directory?(cloud.tmp_path/"etc"/"poolparty")
75
- FileUtils.cp script_file, cloud.tmp_path/"etc"/"poolparty"
75
+ pack_clouds_dot_rb_and_expected_directories
76
76
 
77
+ dputs("Rsyncing #{cloud.tmp_path/"*"}")
77
78
  rsync(:source => cloud.tmp_path/"*", :destination => "/")
78
- run("chmod +x /etc/poolparty/#{File.basename(script_file)}; /bin/sh /etc/poolparty/#{File.basename(script_file)}").chomp
79
79
  run(cloud.dependency_resolver.compile_command)
80
80
  callback :after_configure
81
81
  end
@@ -95,6 +95,15 @@ module CloudProviders
95
95
  end
96
96
  alias :platform :os # Chef uses platform, aliased for conveneince
97
97
 
98
+ def pack_clouds_dot_rb_and_expected_directories
99
+ %w(lib plugins).each do |dir|
100
+ if File.directory?(d = cloud.clouds_dot_rb_dir/dir)
101
+ dputs("Adding local path: #{d}")
102
+ FileUtils.cp_r d, cloud.tmp_path/cloud.base_config_directory, :verbose => true, :remove_destination => true # req'd for symlinks
103
+ end
104
+ end
105
+ FileUtils.cp cloud.clouds_dot_rb_file, cloud.tmp_path/"/etc/poolparty/clouds.rb"
106
+ end
98
107
  # Determine the os
99
108
  # Default to ubuntu
100
109
  # Send the determine_os.sh script to the node and run it remotely
@@ -51,7 +51,7 @@ module CloudProviders
51
51
  raise StandardError.new("You must pass a :source=>uri option to rsync") unless opts[:source]
52
52
  destination_path = opts[:destination] || opts[:source]
53
53
  rsync_opts = opts[:rsync_opts] || '-va'
54
- cmd_string = "rsync -e 'ssh #{ssh_options}' #{rsync_opts} #{opts[:source]} #{user}@#{host}:#{destination_path}"
54
+ cmd_string = "rsync -L -e 'ssh #{ssh_options}' #{rsync_opts} #{opts[:source]} #{user}@#{host}:#{destination_path}"
55
55
  out = system_run(cmd_string)
56
56
  out
57
57
  end
data/lib/core/file.rb ADDED
@@ -0,0 +1,12 @@
1
+ class File
2
+ class << self
3
+ alias_method :old_symlink, :symlink
4
+ def symlink(old_name, new_name)
5
+ begin
6
+ old_symlink(old_name, new_name)
7
+ rescue Errno::EEXIST
8
+ $stderr.puts "warning: symlinking #{old_name} -> #{new_name}. Already exists"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -111,7 +111,7 @@ module DependencyResolvers
111
111
  when Symbol
112
112
  ":#{obj}"
113
113
  when Hash
114
- "#{obj.map {|k,v| ":#{k} => #{handle_print_variable(v)}" unless v == obj }.compact.join(",\n")}"
114
+ "{#{obj.map {|k,v| ":#{k} => #{handle_print_variable(v)}" unless v == obj }.compact.join(",")}}"
115
115
  else
116
116
  "#{obj}"
117
117
  end
@@ -159,13 +159,15 @@ module DependencyResolvers
159
159
  file_pointers.each do |n,f|
160
160
  f << "\n#{n} Mash.new unless attribute?(\"#{n}\")\n"
161
161
  end
162
- variables.each do |var|
163
-
164
- var_val = handle_print_variable(ProxyObject.new(var, @caller).compile(:value))
162
+ variables.each do |var|
165
163
  if var.parent && !var.parent.is_a?(PoolParty::Cloud)
166
- file_pointers[var.parent.has_method_name] << "#{var.parent.has_method_name}[:#{var.name}] = #{var_val}\n"
164
+ file_pointers[var.parent.has_method_name] << "#{var.parent.has_method_name}[:#{var.name}] ="
165
+ file_pointers[var.parent.has_method_name] << ProxyObject.new(var, @caller).compile(:value)
166
+ file_pointers[var.parent.has_method_name] << "\n"
167
167
  else
168
- file_pointers[:poolparty] << "poolparty[:#{var.name}] = #{var_val}\n"
168
+ file_pointers[:poolparty] << "poolparty[:#{var.name}] = "
169
+ file_pointers[:poolparty] << ProxyObject.new(var, @caller).compile(:value)
170
+ file_pointers[:poolparty] << "\n"
169
171
  end
170
172
  end
171
173
  # Close the files
@@ -32,15 +32,18 @@ module DependencyResolvers
32
32
  meth_name
33
33
  when Symbol
34
34
  @current_printing_method = meth_name
35
- self.send(meth_name).to_s
35
+ self.send(meth_name)
36
36
  else
37
37
  raise PoolParty::PoolPartyError.create("ProxyObjectError", "Compilation of #{proxy.inspect} error. Strings and symbols are supported")
38
38
  end
39
+
40
+ str = handle_print_variable(str) if proxy.class == PoolParty::Resources::Variable
41
+
39
42
  begin
40
43
  ERB.new(str).result(self.send(:binding))
41
44
  rescue Exception => e
42
- p [:error, e, str]
43
- end
45
+ ""
46
+ end
44
47
  end
45
48
 
46
49
  # Print the dsl options in the Erb string format
@@ -73,6 +76,11 @@ module DependencyResolvers
73
76
  end.join("\n")
74
77
  end
75
78
 
79
+ # Print variables
80
+ def handle_print_variable(var)
81
+ DependencyResolvers::Base.handle_print_variable(var)
82
+ end
83
+
76
84
  def instance
77
85
  @caller
78
86
  end
data/lib/poolparty.rb CHANGED
@@ -43,7 +43,9 @@ require "poolparty/pool_party_error"
43
43
  hash
44
44
  symbol
45
45
  proc
46
- time).each do |lib|
46
+ time
47
+ file
48
+ ).each do |lib|
47
49
  require "core/#{lib}"
48
50
  end
49
51
 
@@ -37,8 +37,7 @@ module PoolParty
37
37
  # - stack
38
38
  def run_in_context(o={}, &block)
39
39
  proc = Proc.new do
40
- # Name MUST be set first
41
- set_vars_from_options(:name => o[:name]) if o.has_key?(:name)
40
+ set_vars_from_options(:name => o[:name]) if o.has_key?(:name) # Name MUST be set first
42
41
  set_vars_from_options(o)
43
42
  instance_eval &block if block
44
43
  end
@@ -27,6 +27,8 @@ module PoolParty
27
27
  end
28
28
 
29
29
  def before_compile
30
+ add_monitoring_stack_if_needed
31
+
30
32
  validate_all_resources
31
33
  end
32
34
 
@@ -61,7 +63,7 @@ module PoolParty
61
63
  end
62
64
 
63
65
  # Cloud provider methods
64
- def nodes(o={}); delayed_action {cloud_provider.nodes(o)}; end
66
+ def nodes(o={}); delayed_action {cloud_provider.nodes(o).collect{|n| n.cloud = self; n}}; end
65
67
  def run_instance(o={}); cloud_provider.run_instance(o);end
66
68
  def terminate_instance!(o={}); cloud_provider.terminate_instance!(o);end
67
69
  def describe_instances(o={}); cloud_provider.describe_instances(o);end
@@ -87,7 +89,7 @@ module PoolParty
87
89
 
88
90
  # 1.) Launches a new instance,
89
91
  # 2.) Waits for the instance to get an ip address
90
- # 3.) Waits for port 22 to be open
92
+ # 3.) Waits for port ssh_port to be open
91
93
  # 4.) Calls call_after_launch_instance callbacks
92
94
  # 5.) Executes passed &block, if any
93
95
  # 6.) Returns the new instance object
@@ -98,7 +100,7 @@ module PoolParty
98
100
  instance.cloud = self
99
101
  @instance = instance
100
102
  #wait for an ip and then wait for ssh port, then configure instance
101
- if instance.wait_for_public_ip(timeout) && instance.wait_for_port(22, :timeout=>timeout)
103
+ if instance.wait_for_public_ip(timeout) && instance.wait_for_port(ssh_port, :timeout=>timeout)
102
104
  callback :after_launch_instance
103
105
  instance.callback :before_bootstrap
104
106
  instance.bootstrap!
@@ -109,7 +111,7 @@ module PoolParty
109
111
  block.call(instance) if block
110
112
  instance
111
113
  else
112
- raise StandardError.new("Instance port 22 not available")
114
+ raise StandardError.new("Instance port #{ssh_port} not available")
113
115
  end
114
116
  instance.refresh!
115
117
  instance
@@ -126,7 +128,7 @@ module PoolParty
126
128
 
127
129
  # convenience method to loop thru all the nodes and configure them
128
130
  def configure!(opts={}, threaded=true)
129
- nodes.collect{|n| n.configure!}
131
+ nodes.collect{|n| n.configure! }
130
132
  end
131
133
 
132
134
  # Run command/s on all nodes in the cloud.
@@ -177,6 +179,19 @@ module PoolParty
177
179
  end
178
180
  end
179
181
 
182
+ # Add the monitoring stack
183
+ def add_monitoring_stack_if_needed
184
+ if monitors.size > 0
185
+
186
+ run_in_context do
187
+ %w(collectd hermes).each do |m|
188
+ self.send m.to_sym
189
+ end
190
+ end
191
+
192
+ end
193
+ end
194
+
180
195
  # Take the cloud's resources and compile them down using
181
196
  # the defined (or the default dependency_resolver, chef)
182
197
  def compile(caller=nil)
@@ -11,6 +11,7 @@ module PoolParty
11
11
  default_options(
12
12
  :user => "root",
13
13
  :os => :ubuntu,
14
+ :ssh_port => 22,
14
15
  :tmp_path => "/tmp/poolparty",
15
16
  :poolparty_home_path => "#{ENV["HOME"]}/.poolparty",
16
17
  :ec2_home => "#{ENV["HOME"]}/.ec2",
@@ -2,11 +2,7 @@
2
2
  Simply a stub class for documentation purposes
3
3
  Plugins are all resources
4
4
  =end
5
- module PoolParty
6
- class Plugin
7
- end
8
- end
9
5
 
10
- %w(apache git rails).each do |plugin|
6
+ %w(apache git rails collectd hermes).each do |plugin|
11
7
  require "plugins/#{plugin}"
12
8
  end
@@ -50,7 +50,7 @@ module PoolParty
50
50
  passenger_configs
51
51
 
52
52
  has_exec "install_passenger_script" do
53
- command "passenger-install-apache2-module -auto"
53
+ command "passenger-install-apache2-module --auto"
54
54
  notifies get_exec("restart-apache2"), :run
55
55
  requires get_exec("restart-apache2")
56
56
  requires get_package("apache2")
@@ -157,14 +157,16 @@ PassengerRuby <%= @node[:languages][:ruby][:ruby_bin] %>
157
157
  end
158
158
 
159
159
  def install_site(name, opts={})
160
- opts.merge!(:name => "/etc/apache2/sites-available/#{name}")
160
+ sitename = name
161
+
162
+ opts.merge!(:name => "/etc/apache2/sites-available/#{sitename}")
161
163
  has_directory(:name => "/etc/apache2/sites-available")
162
164
  has_file(opts) unless opts[:no_file]
163
- has_exec(:name => "/usr/sbin/a2ensite #{name}") do
165
+ has_exec(:name => "/usr/sbin/a2ensite #{sitename}") do
164
166
  notifies get_exec("reload-apache2"), :run
165
167
  requires get_exec("reload-apache2")
166
- requires get_file("/etc/apache2/sites-available/#{name}")
167
- not_if "/bin/sh -c '[ -L /etc/apache2/sites-enabled/#{name} ] && [ /etc/apache2/sites-enabled/#{name} -ef /etc/apache2/sites-available/#{name} ]'"
168
+ requires get_file("/etc/apache2/sites-available/#{sitename}")
169
+ not_if "/bin/sh -c '[ -L /etc/apache2/sites-enabled/#{sitename} ] && [ /etc/apache2/sites-enabled/#{sitename} -ef /etc/apache2/sites-available/#{sitename} ]'"
168
170
  end
169
171
  end
170
172
 
@@ -202,4 +204,4 @@ end
202
204
  $:.unshift(File.dirname(__FILE__))
203
205
  %w(php5 virtual_host passenger_site).each do |lib|
204
206
  require "apache2/#{lib}"
205
- end
207
+ end
@@ -0,0 +1,24 @@
1
+ module PoolParty
2
+ module Resources
3
+
4
+ class Collectd < Resource
5
+
6
+ PoolParty::Resources::FileResource.has_searchable_paths(:prepend_paths=> [File.dirname(__FILE__)+'/collectd/templates'])
7
+
8
+ def after_loaded
9
+ has_package 'collectd'
10
+ %w(rrdtool librrd-dev librrd-ruby libsensors-dev libsnmp-dev collectd collectd-dev).each{|pkg|
11
+ has_package pkg
12
+ }
13
+ has_gem_package "astro-collectd"
14
+
15
+ has_variable 'server', "localhost"
16
+ has_file '/etc/collectd/collectd.conf' do
17
+ template 'collectd.conf.erb'
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end