auser-poolparty 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/CHANGELOG +8 -0
  2. data/README.txt +10 -10
  3. data/Rakefile +30 -21
  4. data/{web/static/site/images → assets}/clouds.png +0 -0
  5. data/bin/instance +39 -34
  6. data/bin/pool +44 -29
  7. data/bin/poolnotify +34 -0
  8. data/config/haproxy.conf +1 -1
  9. data/config/heartbeat_authkeys.conf +1 -1
  10. data/config/monit/haproxy.monit.conf +2 -1
  11. data/config/nginx.conf +1 -1
  12. data/config/reconfigure_instances_script.sh +28 -9
  13. data/config/sample-config.yml +1 -1
  14. data/lib/core/string.rb +3 -0
  15. data/lib/modules/ec2_wrapper.rb +47 -22
  16. data/lib/modules/file_writer.rb +38 -0
  17. data/lib/modules/sprinkle_overrides.rb +32 -0
  18. data/lib/modules/vlad_override.rb +5 -4
  19. data/lib/poolparty.rb +14 -10
  20. data/lib/poolparty/application.rb +33 -19
  21. data/lib/poolparty/master.rb +227 -105
  22. data/lib/poolparty/optioner.rb +8 -4
  23. data/lib/poolparty/plugin.rb +34 -4
  24. data/lib/poolparty/provider/packages/haproxy.rb +0 -15
  25. data/lib/poolparty/provider/packages/heartbeat.rb +1 -1
  26. data/lib/poolparty/provider/packages/ruby.rb +6 -6
  27. data/lib/poolparty/provider/packages/s3fuse.rb +9 -2
  28. data/lib/poolparty/provider/provider.rb +65 -25
  29. data/lib/poolparty/remote_instance.rb +95 -74
  30. data/lib/poolparty/remoter.rb +48 -37
  31. data/lib/poolparty/remoting.rb +41 -17
  32. data/lib/poolparty/scheduler.rb +4 -4
  33. data/lib/poolparty/tasks.rb +1 -1
  34. data/lib/poolparty/tasks/package.rake +53 -0
  35. data/lib/poolparty/tasks/plugins.rake +1 -1
  36. data/poolparty.gemspec +50 -58
  37. data/spec/application_spec.rb +28 -0
  38. data/spec/core_spec.rb +9 -0
  39. data/spec/ec2_wrapper_spec.rb +87 -0
  40. data/spec/file_writer_spec.rb +73 -0
  41. data/spec/files/describe_response +37 -0
  42. data/spec/files/multi_describe_response +69 -0
  43. data/spec/files/remote_desc_response +37 -0
  44. data/spec/helpers/ec2_mock.rb +3 -0
  45. data/spec/master_spec.rb +302 -78
  46. data/spec/monitors/cpu_monitor_spec.rb +2 -1
  47. data/spec/monitors/memory_spec.rb +1 -0
  48. data/spec/monitors/misc_monitor_spec.rb +1 -0
  49. data/spec/monitors/web_spec.rb +1 -0
  50. data/spec/optioner_spec.rb +12 -0
  51. data/spec/plugin_manager_spec.rb +10 -10
  52. data/spec/plugin_spec.rb +6 -3
  53. data/spec/pool_binary_spec.rb +3 -0
  54. data/spec/poolparty_spec.rb +12 -7
  55. data/spec/provider_spec.rb +1 -0
  56. data/spec/remote_instance_spec.rb +18 -18
  57. data/spec/remoter_spec.rb +4 -2
  58. data/spec/remoting_spec.rb +10 -2
  59. data/spec/scheduler_spec.rb +0 -6
  60. data/spec/spec_helper.rb +13 -0
  61. metadata +83 -52
  62. data/Manifest +0 -115
  63. data/lib/poolparty/tmp.rb +0 -46
  64. data/misc/basics_tutorial.txt +0 -142
  65. data/web/static/conf/nginx.conf +0 -22
  66. data/web/static/site/images/balloon.png +0 -0
  67. data/web/static/site/images/cb.png +0 -0
  68. data/web/static/site/images/railsconf_preso_img.png +0 -0
  69. data/web/static/site/index.html +0 -71
  70. data/web/static/site/javascripts/application.js +0 -3
  71. data/web/static/site/javascripts/corner.js +0 -178
  72. data/web/static/site/javascripts/jquery-1.2.6.pack.js +0 -11
  73. data/web/static/site/misc.html +0 -42
  74. data/web/static/site/storage/pool_party_presentation.pdf +0 -0
  75. data/web/static/site/stylesheets/application.css +0 -100
  76. data/web/static/site/stylesheets/reset.css +0 -17
  77. data/web/static/src/layouts/application.haml +0 -25
  78. data/web/static/src/pages/index.haml +0 -25
  79. data/web/static/src/pages/misc.haml +0 -5
  80. data/web/static/src/stylesheets/application.sass +0 -100
@@ -3,11 +3,15 @@ module PoolParty
3
3
  # Parse the command line options for options without a switch
4
4
  def self.parse(argv, safe=[])
5
5
  args = []
6
+ # Default options
7
+ safe.push "-v"
8
+ safe.push "-i"
9
+
6
10
  argv.each_with_index do |arg,i|
7
- unless arg.index("-")
8
- args << arg
9
- else
10
- argv.delete_at(i+1) unless safe.include?(arg)
11
+ unless arg.index("-") == 0# && !arg.match(/(?:[^"']+)/)
12
+ args << arg
13
+ else
14
+ argv.shift unless safe.include?(arg)
11
15
  end
12
16
  end
13
17
  args
@@ -12,14 +12,14 @@ module PoolParty
12
12
  # create_methods :install, RemoteInstance
13
13
  # will give the following methods to the class
14
14
  # before_install and after_install on the RemoteInstance
15
- def self.create_methods(name, klass)
15
+ def self.create_methods(name, klass, opts={})
16
16
  str = ""
17
17
  %w(before after).each do |time|
18
18
  str << <<-EOE
19
19
  def self.#{time}_#{name}(*meth)
20
20
  callee = self
21
21
  #{klass}.class_eval do
22
- meth.each {|m| #{time} :#{name}, {m.to_sym => callee.to_s}}
22
+ meth.each {|m| #{time} :#{name}, {m.to_sym => callee.to_s }}
23
23
  end
24
24
  end
25
25
  EOE
@@ -27,10 +27,35 @@ module PoolParty
27
27
  eval str
28
28
  end
29
29
 
30
+ def self.user_tasks str
31
+ PoolParty::RemoteInstance.user_tasks << str
32
+ end
33
+
34
+ def self.install_package_string(str)
35
+ PoolParty::Provider.define_user_package str
36
+ end
37
+
38
+ def self.define_package_string(str)
39
+ PoolParty::Provider.define_user_install str
40
+ end
41
+
42
+ def self.define_global_file(name, &block)
43
+ PoolParty::Master.define_global_user_file(name, &block)
44
+ end
45
+
46
+ def self.define_node_file(name, &block)
47
+ PoolParty::Master.define_node_user_file(name, &block)
48
+ end
49
+
50
+ def read_config_file(filename)
51
+ return {} unless filename
52
+ YAML.load(open(filename).read)
53
+ end
54
+
30
55
  %w(install configure associate_public_ip become_master).each do |method|
31
56
  create_methods method, RemoteInstance
32
57
  end
33
- %w(start start_monitor scale_cloud reconfiguration add_instance terminate_instance check_stats).each do |method|
58
+ %w(start start_monitor install_cloud configure_cloud scale_cloud reconfiguration add_instance terminate_instance check_stats).each do |method|
34
59
  create_methods method, Master
35
60
  end
36
61
  %w(define_tasks).each do |method|
@@ -38,6 +63,11 @@ module PoolParty
38
63
  end
39
64
  %w(run_tasks).each do |method|
40
65
  create_methods method, Scheduler
41
- end
66
+ end
67
+
68
+ %w(load_packages).each do |method|
69
+ create_methods method, Provider
70
+ end
71
+
42
72
  end
43
73
  end
@@ -1,20 +1,5 @@
1
1
  # Install haproxy
2
-
3
- def post_install_string
4
- %w(
5
- "echo 'Configuring haproxy logging'"
6
- "sed -i 's/ENABLED=0/ENABLED=1/g' /etc/default/haproxy"
7
- "sed -i 's/SYSLOGD=\"\"/SYSLOGD=\"-r\"/g' /etc/default/syslogd"
8
- "echo 'local0.* /var/log/haproxy.log' >> /etc/syslog.conf && /etc/init.d/sysklogd restart"
9
- "/etc/init.d/haproxy restart"
10
- )
11
- end
12
-
13
2
  package :haproxy, :provides => :proxy do
14
3
  description 'Haproxy proxy'
15
- # version '1.2.18'
16
- # source "http://haproxy.1wt.eu/download/1.2/src/haproxy-#{version}.tar.gz"
17
4
  apt %w( haproxy )
18
-
19
- post :install, post_install_string
20
5
  end
@@ -1,4 +1,4 @@
1
- package :heartbeat do
1
+ package :heartbeat, :provides => :failover do
2
2
  description "Heartbeat Linux HA project"
3
3
  apt %w(heartbeat-2)
4
4
  end
@@ -2,7 +2,7 @@ package :ruby do
2
2
  description 'Ruby Virtual Machine'
3
3
  # version '1.8.6'
4
4
  # source "ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-#{version}-p111.tar.gz" # implicit :style => :gnu
5
- apt %w( ruby )
5
+ apt %w( ruby ruby1.8-dev )
6
6
  requires :ruby_dependencies
7
7
  end
8
8
 
@@ -18,19 +18,19 @@ package :rubygems do
18
18
  # custom_install 'ruby setup.rb'
19
19
  # end
20
20
  apt %w( rubygems )
21
- post :install, "gem update --system"
21
+ post :install, "gem update --system", "gem sources -a http://gems.github.com"
22
22
  requires :ruby
23
23
  end
24
24
 
25
25
  package :poolparty_required_gems do
26
26
  description "required gems"
27
- gems %w(SQS aws-s3 amazon-ec2 aska rake)
27
+ gems %w( SQS aws-s3 amazon-ec2 aska rake rcov auser-poolparty )
28
28
  end
29
29
 
30
- package :poolparty do
30
+ package :required_gems do
31
31
  description "Pool party gem"
32
- gem "auser-pool-party" do
33
- source 'http://gems.github.com'
32
+ gem "poolparty" do
33
+ source 'http://gems.github.com -y'
34
34
  end
35
35
 
36
36
  required :poolparty_required_gems
@@ -1,11 +1,18 @@
1
1
  package :s3fs do
2
2
  description "S3 Fuse project"
3
- source "http://s3fs.googlecode.com/files/s3fs-r166-source.tar.gz"
4
-
3
+ source "http://s3fs.googlecode.com/files/s3fs-r166-source.tar.gz" do
4
+ custom_dir 's3fs'
5
+ custom_install "make"
6
+
7
+ post :install, "mv s3fs /usr/bin"
8
+ end
9
+
5
10
  requires :s3fs_deps
6
11
  end
7
12
 
8
13
  package :s3fs_deps do
9
14
  description "S3 Fuse project dependencies"
10
15
  apt %w( libcurl4-openssl-dev libxml2-dev libfuse-dev )
16
+
17
+ requires :build_essential
11
18
  end
@@ -1,36 +1,83 @@
1
- require "sprinkle"
2
-
3
1
  module PoolParty
4
2
  class Provider
3
+ class << self
4
+ attr_accessor :user_packages
5
+ end
5
6
 
6
7
  def self.install_poolparty(ips)
8
+ @ips = ips
7
9
 
8
- $:.unshift( File.dirname(__FILE__) )
9
-
10
- load_str = []
11
-
12
- Dir["#{File.expand_path(File.dirname(__FILE__))}/packages/*"].each {|f| load_str << open(f).read}
10
+ load_str = load_packages
13
11
 
14
12
  script=<<-EOS
15
-
16
- #{load_str.join("\n")}
13
+ #{load_str.join("\n")}
17
14
 
18
15
  policy :poolparty, :roles => :app do
19
16
  requires :git
20
17
  requires :ruby
18
+ requires :failover
19
+ requires :proxy
21
20
  requires :monit
22
21
  requires :s3fs
23
- requires :rsync
24
- requires :heartbeat
25
- requires :poolparty
26
- end
22
+ requires :rsync
23
+ requires :required_gems
24
+ end
25
+
26
+ #{install_from_sprinkle_string}
27
+ EOS
28
+
29
+ PoolParty.message "Installing required poolparty paraphernalia"
30
+ Sprinkle::Script.sprinkle script
31
+ end
32
+
33
+ def self.install_userpackages(ips)
34
+ @ips = ips
35
+
36
+ script=<<-EOS
37
+ #{load_strings.join("\n")}
27
38
 
28
- deployment do
39
+ policy :userpackages, :roles => :app do
40
+ #{user_packages.join("\n")}
41
+ end
42
+
43
+ #{install_from_sprinkle_string}
44
+ EOS
45
+
46
+ PoolParty.message "Installing user defined packages"
47
+ Sprinkle::Script.sprinkle script# unless load_strings.empty?
48
+ end
49
+
50
+ def self.define_user_package string
51
+ user_packages << string
52
+ end
53
+
54
+ def self.define_user_install string
55
+ load_strings << string
56
+ end
57
+
58
+ def self.user_packages
59
+ @@user_packages ||= []
60
+ end
61
+
62
+ def self.load_strings
63
+ @@load_strings ||= []
64
+ end
65
+
66
+ def self.load_packages
67
+ load_str = []
68
+ returning load_str do
69
+ Dir["#{File.expand_path(File.dirname(__FILE__))}/packages/*"].each {|f| load_str << open(f).read}
70
+ end
71
+ end
72
+
73
+ def self.install_from_sprinkle_string
74
+ <<-EOS
75
+ deployment do
29
76
  delivery :vlad do
30
77
 
31
- set :ssh_cmd, '#{RemoteInstance.ssh_string}'
78
+ set :ssh_flags, "#{RemoteInstance.ssh_string.gsub(/ssh/, '')}"
32
79
 
33
- #{string_roles_from_ips(ips)}
80
+ #{string_roles_from_ips(@ips)}
34
81
  end
35
82
 
36
83
  source do
@@ -39,17 +86,10 @@ module PoolParty
39
86
  builds '/root/builds'
40
87
  end
41
88
 
42
- end
89
+ end
43
90
  EOS
44
-
45
- PoolParty.message "Installing required poolparty paraphernalia"
46
- install_from_sprinkle_string script
47
91
  end
48
-
49
- def self.install_from_sprinkle_string(str)
50
- Sprinkle::Script.sprinkle str
51
- end
52
-
92
+
53
93
  def self.string_roles_from_ips(ips)
54
94
  ips.collect do |ip|
55
95
  "role :app, '#{ip}'"
@@ -5,13 +5,14 @@ module PoolParty
5
5
  # ############################
6
6
  include PoolParty
7
7
  include Callbacks
8
+ include FileWriter
8
9
 
9
- attr_reader :ip, :instance_id, :name, :status, :launching_time, :stack_installed
10
- attr_accessor :name, :number, :scp_configure_file, :configure_file, :plugin_string
10
+ attr_reader :ip, :instance_id, :name, :status, :launching_time, :stack_installed, :keypair
11
+ attr_accessor :name, :number, :scp_configure_file, :configure_file, :plugin_string, :keypair
11
12
 
12
13
  # CALLBACKS
13
- after :install, :mark_installed
14
-
14
+ after :install, :mark_installed
15
+ after :configure, :associate_public_ip
15
16
  def initialize(obj={})
16
17
  super
17
18
 
@@ -21,6 +22,7 @@ module PoolParty
21
22
  @number = obj[:number] || 0 # Defaults to the master
22
23
  @status = obj[:status] || "running"
23
24
  @launching_time = obj[:launching_time] || Time.now
25
+ @keypair = obj[:keypair] || Application.keypair
24
26
  end
25
27
 
26
28
  # Host entry for this instance
@@ -65,81 +67,100 @@ module PoolParty
65
67
  ssh("monit #{cmd} all")
66
68
  end
67
69
  end
68
- # Configure the server with the new, sexy shell script
69
- # This compiles all the scp commands into a shell script and then executes it
70
- # then it will compile a list of the commands to operate on the instance
71
- # and execute it
72
- # This is how the cloud reconfigures itself
73
- def configure(caller=nil)
74
- associate_public_ip
75
- scp_basic_config_files
76
-
77
- Master.with_nodes do |node|
78
- # These are node-specific
79
- PoolParty.message "configuring #{node.name}"
80
- node.scp_specific_config_files
70
+ def configure_tasks
71
+ {
72
+ :move_hostfile => change_hostname,
73
+ :config_master => configure_master,
74
+ :move_config_file => move_config_file,
75
+ :set_hostname => change_hostname,
76
+ :mount_s3_drive => mount_s3_drive,
77
+ :update_plugins => update_plugin_string,
78
+ :configure_monit => configure_monit,
79
+ :configure_authkeys => configure_authkeys,
80
+ :configure_resource_d => configure_resource_d,
81
+ :configure_haproxy => setup_haproxy,
82
+ :configure_heartbeat => configure_heartbeat,
83
+ :user_tasks => user_tasks
84
+ }
85
+ end
86
+ def user_tasks
87
+ @@user_tasks ||= []
88
+ end
89
+ def move_config_file
90
+ <<-EOC
91
+ mv #{remote_base_tmp_dir}/config.yml ~/.config
92
+ mkdir -p ~/.ec2
93
+ mv #{remote_base_tmp_dir}/keypair ~/.ec2/id_rsa-#{Application.keypair}
94
+ EOC
95
+ end
96
+ def configure_heartbeat
97
+ <<-EOC
98
+ mv #{remote_base_tmp_dir}/ha.cf /etc/ha.d/ha.cf
99
+ /etc/init.d/heartbeat start
100
+ EOC
101
+ end
102
+ def configure_authkeys
103
+ <<-EOC
104
+ mkdir -p /etc/ha.d
105
+ mv #{remote_base_tmp_dir}/authkeys /etc/ha.d/
106
+ EOC
107
+ end
108
+
109
+ def configure_master
110
+ if master?
111
+ <<-EOC
112
+ pool maintain -c ~/.config -l ~/plugins
113
+ EOC
114
+ else
115
+ ""
81
116
  end
82
- configure_basics_through_ssh
83
117
  end
84
118
 
85
- def configure_basics_through_ssh
86
- # -l #{Application.plugin_dir}
87
- cmd=<<-EOC
88
- #{update_plugin_string}
89
- chmod 700 /etc/monit/monitrc
90
- pool maintain -c ~/.config
91
- hostname -v #{name}
92
- /usr/bin/s3fs #{Application.shared_bucket} -o accessKeyId=#{Application.access_key} -o secretAccessKey=#{Application.secret_access_key} -o nonempty /data
119
+ def configure_resource_d
120
+ <<-EOC
121
+ mkdir -p /etc/ha.d/resource.d
122
+ mv #{remote_base_tmp_dir}/cloud_master_takeover /etc/ha.d/resource.d
123
+ mv #{remote_base_tmp_dir}/resource.d/* /etc/ha.d/resource.d
93
124
  EOC
94
- execute_tasks do
95
- ssh(cmd.runnable)
96
- end
97
125
  end
98
126
 
99
- def scp_string(src,dest,opts={})
127
+ def configure_monit
128
+ <<-EOC
129
+ mv #{remote_base_tmp_dir}/monitrc /etc/monit/monitrc
130
+ mkdir -p /etc/monit.d/
131
+ mv #{remote_base_tmp_dir}/monit.d/* /etc/monit.d/
132
+ chown #{Application.username} /etc/monit/monitrc
133
+ chmod 700 /etc/monit/monitrc
134
+ EOC
100
135
  end
101
136
 
102
- def scp_basic_config_files
103
- cmd=<<-EOC
104
- mkdir -p /etc/ha.d/resource.d
105
- mkdir -p /etc/monit
106
- mkdir -p /etc/monit.d
137
+ def change_hostname
138
+ <<-EOC
139
+ mv #{remote_base_tmp_dir}/#{name}-hosts /etc/hosts
140
+ hostname -v #{name}
107
141
  EOC
108
- execute_tasks do
109
- scp(Application.heartbeat_authkeys_config_file, "/etc/ha.d", :dir => "/etc/ha.d/resource.d")
110
- scp(conf_file("cloud_master_takeover"), "/etc/ha.d/resource.d/cloud_master_takeover", :dir => "/etc/ha.d/resource.d/")
111
-
112
- scp(Application.config_file, "~/.config") if Application.config_file
113
- Dir["#{root_dir}/config/resource.d/*"].each do |file|
114
- scp(file, "/etc/ha.d/resource.d/#{File.basename(file)}")
115
- end
116
- scp(Application.monit_config_file, "/etc/monit/monitrc", :dir => "/etc/monit")
117
- Dir["#{root_dir}/config/monit.d/*"].each do |file|
118
- scp(file, "/etc/monit.d/#{File.basename(file)}")
119
- end
120
-
121
- `mkdir -p tmp/`
122
- File.open("tmp/pool-party-haproxy.cfg", 'w') {|f| f.write(Master.build_haproxy_file) }
123
- scp("tmp/pool-party-haproxy.cfg", "/etc/haproxy.cfg")
124
- end
125
142
  end
126
- def scp_specific_config_files
127
- execute_tasks({:dont_set_hosts => true}) do
128
- if Master.requires_heartbeat?
129
- hafile = "tmp/#{name}-pool-party-ha.cf"
130
- File.open(hafile, 'w') {|f| f.write(Master.build_heartbeat_config_file_for(self)) }
131
- single_scp(hafile, "/etc/ha.d/ha.cf")
132
-
133
- haresources_file = "tmp/#{name}-pool-party-haresources"
134
- File.open(haresources_file, 'w') {|f| f.write(Master.build_heartbeat_resources_file_for(self)) }
135
- single_scp(haresources_file, "/etc/ha/haresources", :dir => "/etc/ha")
136
- end
137
- hosts_file = "tmp/#{name}-pool-party-hosts"
138
- File.open(hosts_file, 'w') {|f| f.write(Master.build_hosts_file_for(self)) }
139
- single_scp(hosts_file, "/etc/hosts")
140
- end
143
+
144
+ def setup_haproxy
145
+ <<-EOS
146
+ mv #{remote_base_tmp_dir}/haproxy /etc/haproxy.cfg
147
+ sed -i "s/ENABLED=0/ENABLED=1/g" /etc/default/haproxy
148
+ sed -i 's/SYSLOGD=""/SYSLOGD="-r"/g' /etc/default/syslogd
149
+ echo "local0.* /var/log/haproxy.log" >> /etc/syslog.conf && /etc/init.d/sysklogd restart
150
+ /etc/init.d/haproxy restart
151
+ EOS
141
152
  end
142
153
 
154
+ def mount_s3_drive
155
+ if Application.shared_bucket.empty?
156
+ ""
157
+ else
158
+ <<-EOC
159
+ mkdir -p /data && /usr/bin/s3fs #{Application.shared_bucket} -o accessKeyId=#{Application.access_key} -o secretAccessKey=#{Application.secret_access_key} -o nonempty /data
160
+ EOC
161
+ end
162
+ end
163
+
143
164
  # Installs with one commandline and an scp, rather than 10
144
165
  def install
145
166
  # unless stack_installed?
@@ -156,7 +177,7 @@ module PoolParty
156
177
  run_now "ls -l"
157
178
  end
158
179
  # Associate a public ip if it is set and this is the master
159
- def associate_public_ip
180
+ def associate_public_ip(c)
160
181
  associate_address_with(Application.public_ip, @instance_id) if master? && Application.public_ip && !Application.public_ip.empty?
161
182
  end
162
183
  # Become the new master
@@ -164,19 +185,20 @@ module PoolParty
164
185
  @master = Master.new
165
186
  @number = 0
166
187
  @master.nodes[0] = self
188
+ @master.configure_cloud
167
189
  configure
168
190
  end
191
+ # Placeholder
192
+ def configure
193
+ end
169
194
  def update_plugin_string
170
195
  reset!
171
196
  str = "mkdir -p #{Application.plugin_dir} && cd #{Application.plugin_dir}\n"
172
197
  installed_plugins.each do |plugin_source|
173
198
  str << "git clone #{plugin_source}\n"
174
199
  end
200
+ str
175
201
  end
176
- def update_plugins(c)
177
- ssh(c.update_plugin_string)
178
- end
179
- after :configure, :update_plugins
180
202
  # Is this the master and if not, is the master running?
181
203
  def is_not_master_and_master_is_not_running?
182
204
  !master? && !Master.is_master_responding?
@@ -190,7 +212,6 @@ module PoolParty
190
212
  File.join(PoolParty.root_dir, "config", name)
191
213
  end
192
214
  end
193
-
194
215
  # Description in the rake task
195
216
  def description
196
217
  case @status
@@ -203,7 +224,7 @@ module PoolParty
203
224
  end
204
225
  end
205
226
  def stack_installed?
206
- @stack_installed ||= (run_now('echo ~/.installed') == "installed")
227
+ @stack_installed ||= false
207
228
  end
208
229
  def mark_installed(caller=nil)
209
230
  run_now("echo 'installed' > ~/.installed")