auser-poolparty 0.2.78 → 0.2.79

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -16,6 +16,7 @@ bin/cloud-maintain
16
16
  bin/cloud-osxcopy
17
17
  bin/cloud-provision
18
18
  bin/cloud-refresh
19
+ bin/cloud-rsync
19
20
  bin/cloud-run
20
21
  bin/cloud-ssh
21
22
  bin/cloud-start
@@ -81,6 +82,7 @@ lib/erlang/messenger/ebin/pm_node.beam
81
82
  lib/erlang/messenger/ebin/pm_node_rel-0.1.rel
82
83
  lib/erlang/messenger/ebin/pm_node_supervisor.beam
83
84
  lib/erlang/messenger/ebin/pm_packager.beam
85
+ lib/erlang/messenger/ebin/pm_spawner.beam
84
86
  lib/erlang/messenger/ebin/pm_strings.beam
85
87
  lib/erlang/messenger/ebin/utils.beam
86
88
  lib/erlang/messenger/include/defines.hrl
@@ -160,6 +162,7 @@ lib/erlang/messenger/src/pm_master_supervisor.erl
160
162
  lib/erlang/messenger/src/pm_node.erl
161
163
  lib/erlang/messenger/src/pm_node_supervisor.erl
162
164
  lib/erlang/messenger/src/pm_packager.erl
165
+ lib/erlang/messenger/src/pm_spawner.erl
163
166
  lib/erlang/messenger/src/pm_strings.erl
164
167
  lib/erlang/messenger/src/utils.erl
165
168
  lib/erlang/messenger/useful_snippets
@@ -391,7 +394,6 @@ test/test_generator_helper.rb
391
394
  test/test_helper.rb
392
395
  test/test_pool_spec_generator.rb
393
396
  test/test_poolparty.rb
394
- website/index.html
395
397
  website/index.txt
396
398
  website/javascripts/rounded_corners_lite.inc.js
397
399
  website/stylesheets/code.css
data/PostInstall.txt CHANGED
@@ -1,4 +1,4 @@
1
- Get ready to jump in the pool, you just installed PoolParty! (Updated at 09:44 12/05/08)
1
+ Get ready to jump in the pool, you just installed PoolParty! (Updated at 13:46 12/06/08)
2
2
 
3
3
  To get started, run the generator:
4
4
 
data/bin/cloud-maintain CHANGED
@@ -22,7 +22,7 @@ o.loaded_clouds.each do |cloud|
22
22
  elsif maximum_number_of_instances_are_running?
23
23
  vputs "#{list_of_running_instances.size} running instances of between #{minimum_instances} and #{maximum_instances}"
24
24
  vputs "Shutting down non-master instance"
25
- contract_cloud_if_necessary( !testing )
25
+ contract_cloud_if_necessary( testing ? true : false )
26
26
  end
27
27
  vputs "Cloud is maintained"
28
28
  end
data/bin/cloud-rsync ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
3
+ require "poolparty"
4
+ require "poolpartycl"
5
+
6
+ o = PoolParty::Optioner.new(ARGV, {:extra_help => "\nUsage: cloud [options] rsync source target\n\n"}) do |opts, optioner|
7
+ opts.on('-n name', '--name name', 'Listing for cloud name') { |c| optioner.cloudname c }
8
+ opts.on('-i num', '--id num', 'Instance num to ssh (default: 0)') { |i| optioner.num i }
9
+ end
10
+
11
+ @instance_number = (o.num || 0 ).to_i
12
+
13
+ if o.unflagged_args.length > 1
14
+ @target = o.unflagged_args.pop
15
+ @source = o.unflagged_args.pop
16
+ else
17
+ @source = o.unflagged_args.pop
18
+ @target = ''
19
+ end
20
+
21
+ o.loaded_clouds.each do |cloud|
22
+
23
+ with_cloud(cloud, {:source=>@source, :target=>@target, :instance_number=>@instance_number }) do
24
+ puts header("rsyncing")
25
+ rsync_to source, target, instance_number
26
+ end
27
+
28
+ end
@@ -133,7 +133,7 @@ init(Args) ->
133
133
  %% Description: Handling call messages
134
134
  %%--------------------------------------------------------------------
135
135
  handle_call({run_command, Cmd}, _From, State) ->
136
- Reply = os:cmd(". /etc/profile && server-fire-cmd \""++Cmd++"\""),
136
+ Reply = os:cmd(Cmd),
137
137
  {reply, Reply, State};
138
138
  handle_call({update_load, Type, Load}, _From, State) ->
139
139
  {Type, NewState} = store_load_for_type(Type, Load, State),
@@ -197,5 +197,4 @@ code_change(_OldVsn, State, _Extra) ->
197
197
  {ok, State}.
198
198
 
199
199
  % Private
200
- server_location() ->
201
- global:whereis_name(node()).
200
+ server_location() -> global:whereis_name(node()).
@@ -0,0 +1,213 @@
1
+ %
2
+ % pm_spawner.erl
3
+ % Spawn a process in this gen_server remotely
4
+ % and hear back from it when it's got stuff to say
5
+ %
6
+ % Created by Ari Lerner on 2008-12-05.
7
+ % Copyright 2008 CitrusByte. All rights reserved.
8
+ %
9
+ -module (pm_spawner).
10
+ -behaviour(gen_server).
11
+
12
+ -include_lib("../include/defines.hrl").
13
+
14
+ %% API
15
+ -export([start_link/0]).
16
+ -export ([run_command/1, run_command/2, check_command/1]).
17
+
18
+ %% gen_server callbacks
19
+ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
20
+
21
+ -record(state, {
22
+ processes = ?DICT:new() % Array of the output
23
+ }).
24
+ -define(SERVER, ?MODULE).
25
+
26
+ %%--------------------------------------------------------------------
27
+ %% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
28
+ %% Description: Starts the server
29
+ %%--------------------------------------------------------------------
30
+ start_link() -> gen_server:start_link({global, ?MODULE}, ?MODULE, [], []).
31
+
32
+ %%====================================================================
33
+ %% gen_server callbacks
34
+ %%====================================================================
35
+
36
+ %%--------------------------------------------------------------------
37
+ %% Function: init(Args) -> {ok, State} |
38
+ %% {ok, State, Timeout} |
39
+ %% ignore |
40
+ %% {stop, Reason}
41
+ %% Description: Initiates the server
42
+ %%--------------------------------------------------------------------
43
+ init([]) ->
44
+ % process_flag(trap_exit, true),
45
+ {ok, #state{
46
+ processes = ?DICT:new()
47
+ }}.
48
+
49
+ %%--------------------------------------------------------------------
50
+ %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
51
+ %% {reply, Reply, State, Timeout} |
52
+ %% {noreply, State} |
53
+ %% {noreply, State, Timeout} |
54
+ %% {stop, Reason, Reply, State} |
55
+ %% {stop, Reason, State}
56
+ %% Description: Handling call messages
57
+ %%--------------------------------------------------------------------
58
+ handle_call({run_command, Cmds}, _From, State) ->
59
+ {ok, NewState} = run_command(Cmds, State),
60
+ ?TRACE("storing into state from call", [Cmds, NewState]),
61
+ {reply, ok, NewState};
62
+ handle_call({check_command, Cmd}, _From, State) ->
63
+ AtomCommand = erlang:list_to_atom(Cmd),
64
+ ?TRACE("is_key for ", [AtomCommand, ?DICT:is_key(AtomCommand, State#state.processes)]),
65
+ case ?DICT:is_key(AtomCommand, State#state.processes) of
66
+ false ->
67
+ Reply = nil,
68
+ NewState = State;
69
+ true ->
70
+ Pid = ?DICT:fetch(AtomCommand, State#state.processes),
71
+ case erlang:is_pid(Pid) of
72
+ true ->
73
+ Pid ! {self(), collect},
74
+ receive
75
+ {command_response, OutFromCommand} ->
76
+ Reply = OutFromCommand,
77
+ NewState = State#state{processes = ?DICT:store(AtomCommand, OutFromCommand, State#state.processes)};
78
+ Msg ->
79
+ NewState = State,
80
+ Reply = Msg
81
+ after
82
+ 1000 ->
83
+ Pid ! {self(), collect},
84
+ NewState = State,
85
+ Reply = "no output"
86
+ end;
87
+ false ->
88
+ NewState = State,
89
+ Reply = Pid
90
+ end
91
+ end,
92
+ {reply, Reply, NewState};
93
+ handle_call(_Request, _From, State) ->
94
+ Reply = ok,
95
+ {reply, Reply, State}.
96
+ %%--------------------------------------------------------------------
97
+ %% Function: handle_cast(Msg, State) -> {noreply, State} |
98
+ %% {noreply, State, Timeout} |
99
+ %% {stop, Reason, State}
100
+ %% Description: Handling cast messages
101
+ %%--------------------------------------------------------------------
102
+ handle_cast({run_command, Cmd}, State) ->
103
+ {ok, NewState} = run_command(Cmd, State),
104
+ {noreply, NewState};
105
+ handle_cast(_Msg, State) ->
106
+ {noreply, State}.
107
+
108
+ %%--------------------------------------------------------------------
109
+ %% Function: handle_info(Info, State) -> {noreply, State} |
110
+ %% {noreply, State, Timeout} |
111
+ %% {stop, Reason, State}
112
+ %% Description: Handling all non call/cast messages
113
+ %%--------------------------------------------------------------------
114
+ handle_info(_Info, State) ->
115
+ {noreply, State}.
116
+
117
+ %%--------------------------------------------------------------------
118
+ %% Function: terminate(Reason, State) -> void()
119
+ %% Description: This function is called by a gen_server when it is about to
120
+ %% terminate. It should be the opposite of Module:init/1 and do any necessary
121
+ %% cleaning up. When it returns, the gen_server terminates with Reason.
122
+ %% The return value is ignored.
123
+ %%--------------------------------------------------------------------
124
+ terminate(_Reason, _State) ->
125
+ ok.
126
+
127
+ %%--------------------------------------------------------------------
128
+ %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
129
+ %% Description: Convert process state when code is changed
130
+ %%--------------------------------------------------------------------
131
+ code_change(_OldVsn, State, _Extra) ->
132
+ {ok, State}.
133
+
134
+ % Quick helper for running commands
135
+ run_command(Cmd) -> gen_server:call(server_location(), {run_command, Cmd}).
136
+ check_command(Cmd) ->
137
+ Command = lists:flatten(io_lib:format("~s", [Cmd])),
138
+ gen_server:call(server_location(), {check_command, Command}).
139
+
140
+ % Run the command, start up the
141
+ run_command(Cmd, State) ->
142
+ Command = lists:flatten(io_lib:format("~s", [Cmd])),
143
+ AtomCommand = erlang:list_to_atom(Command),
144
+ Pid = spawn(fun() -> spawn_command(Command) end),
145
+ Storage = Pid,
146
+ ?TRACE("storing into state", [AtomCommand]),
147
+ NewState = State#state{processes = ?DICT:store(AtomCommand, Storage, State#state.processes)},
148
+ {ok, NewState}.
149
+
150
+ spawn_command(Command) ->
151
+ Port = erlang:open_port({spawn, Command}, [stream, exit_status, stderr_to_stdout, use_stdio]),
152
+ ResponsePid = response_reader(Port),
153
+ spawn_command_loop(Command, Port, ResponsePid).
154
+
155
+ spawn_command_loop(Command, Port, Responses) ->
156
+ receive
157
+ {Pid, collect} ->
158
+ case erlang:is_pid(Responses) of
159
+ true ->
160
+ io:format("There is no output on your command yet, try again in a few seconds ~p~n", [Responses]),
161
+ spawn_command_loop(Command, Port, Responses);
162
+ false ->
163
+ Pid ! {command_response, Responses}
164
+ end;
165
+ {exit_status, _} ->
166
+ spawn_command_loop(Command, Port, Responses);
167
+ {done, Port, Response} ->
168
+ ?TRACE("Received done message", Response),
169
+ spawn_command_loop(Command, Port, Response);
170
+ {Port, {exit_status, 0}} ->
171
+ ?TRACE("Received exit_status", [Port]),
172
+ Responses ! {Port, {exit_status, 0, self()}},
173
+ receive
174
+ {ok, Resp} ->
175
+ ?TRACE("Received ok back", [Resp]),
176
+ spawn_command_loop(Command, Port, Resp)
177
+ end;
178
+ Mes ->
179
+ ?TRACE("received message", [Mes]),
180
+ Responses ! Mes,
181
+ spawn_command_loop(Command, Port, Responses)
182
+ end.
183
+
184
+ response_reader(Port) ->
185
+ ResponsePid = spawn(fun() -> response_reader_loop(Port, []) end),
186
+ ResponsePid.
187
+
188
+ response_reader_loop(Port, Acc) ->
189
+ receive
190
+ {Port, {data, Bin}} ->
191
+ ?TRACE("received data", [Bin]),
192
+ response_reader_loop(Port, [Bin|Acc]);
193
+ {Port, {exit_status, 0, Pid}} ->
194
+ catch erlang:port_close(Port),
195
+ Response = lists:flatten(lists:reverse(Acc)),
196
+ ?TRACE("received exit_status", [Response, Port]),
197
+ Pid ! {ok, Response};
198
+ {Port, {exit_status, _}} ->
199
+ catch erlang:port_close(Port),
200
+ Output = lists:flatten(lists:reverse(Acc)),
201
+ {error, Output};
202
+ {Pid, get_data} ->
203
+ ?TRACE("get_data for", [Pid, Acc]),
204
+ Pid ! {data, Port, Acc},
205
+ response_reader_loop(Port, Acc);
206
+ {_, collect} ->
207
+ response_reader_loop(Port, Acc);
208
+ Mes ->
209
+ io:format("Unexpected message in response_reader_loop ~p~n", [Mes]),
210
+ response_reader_loop(Port, Acc)
211
+ end.
212
+
213
+ server_location() -> global:whereis_name(?SERVER).
@@ -72,6 +72,7 @@ module PoolParty
72
72
  mode 744
73
73
  template File.join(File.dirname(__FILE__), "..", "templates/puppetrerun")
74
74
  end
75
+
75
76
  has_remotefile(:name => "/usr/bin/puppetcleaner") do
76
77
  mode 744
77
78
  template File.join(File.dirname(__FILE__), "..", "templates/puppetcleaner")
@@ -80,10 +81,10 @@ module PoolParty
80
81
  execute_on_master do
81
82
  has_exec(:name => "update_hosts", :command => ". /etc/profile && server-update-hosts -n #{cloud.name}")
82
83
 
83
- has_cron(:name => "master puppetd runner", :user => Base.user, :minute => "*/15") do
84
- requires get_gempackage("poolparty")
85
- command(PoolParty::Remote::RemoteInstance.puppet_runner_command)
86
- end
84
+ # has_cron(:name => "master puppetd runner", :user => Base.user, :minute => "*/15") do
85
+ # requires get_gempackage("poolparty")
86
+ # command(PoolParty::Remote::RemoteInstance.puppet_runner_command)
87
+ # end
87
88
  has_cron(:name => "Load handler", :user => Base.user, :minute => "*/4") do
88
89
  requires get_gempackage("poolparty")
89
90
  command(". /etc/profile && cloud-handle-load -n #{cloud.name}")
@@ -24,14 +24,21 @@ module Kernel
24
24
  ensure
25
25
  $-v = saved_verbosity
26
26
  end
27
+
28
+ #redirect stdout and stderr to /dev/null and reopen after block
27
29
  def hide_output
28
30
  begin
29
31
  old_stdout = STDOUT.dup
32
+ old_stderr = STDERR.dup
30
33
  STDOUT.reopen(File.open((PLATFORM =~ /mswin/ ? "NUL" : "/dev/null"), 'w'))
34
+ STDERR.reopen(File.open((PLATFORM =~ /mswin/ ? "NUL" : "/dev/null"), 'w'))
31
35
  yield if block_given?
32
36
  ensure
33
37
  STDOUT.flush
34
38
  STDOUT.reopen(old_stdout)
39
+ STDERR.flush
40
+ STDERR.reopen(old_stderr)
35
41
  end
36
42
  end
43
+
37
44
  end
@@ -9,9 +9,12 @@ module PoolParty
9
9
  class Optioner
10
10
  include Configurable
11
11
  include MethodMissingSugar
12
-
13
- def initialize(args=[], opts={}, &block)
14
- @arguments = parse_args(args)
12
+
13
+
14
+ def initialize(args=[], opts={}, &block)
15
+ boolean_args << opts[:boolean_args] if opts.has_key?(:boolean_args)
16
+
17
+ @arguments = parse_args(args)
15
18
  @extra_help = opts.has_key?(:extra_help) ? opts[:extra_help] : ""
16
19
  @abstract = opts.has_key?(:abstract) ? opts[:abstract] : false
17
20
  @load_pools = opts.has_key?(:load_pools) ? opts[:load_pools] : !@abstract
@@ -22,16 +25,43 @@ module PoolParty
22
25
  set_default_options
23
26
  self
24
27
  end
25
-
26
28
  def daemonizeable
27
29
  @opts.on('-d', '--daemonize', 'Daemonize starting the cloud') { self.daemon true }
28
30
  end
29
31
  def cloudnames
30
32
  @opts.on('-n cloudname', '--name name', 'Start cloud by this name') { |c| self.cloudname c }
33
+ end
34
+ def unflagged_args
35
+ @unflagged_args ||= []
36
+ end
37
+ def flagged_args
38
+ @flagged_args ||= []
39
+ end
40
+ def boolean_args
41
+ @boolean_args ||= ['-V', '-h', '-t', '-v']
31
42
  end
32
43
 
33
- def parse_args(argv, safe=[])
34
- argv
44
+ # Break ARGV into 2 arrays, one for flagged options one for unflagged
45
+ # For example the "command -v -i 1 five six -x"
46
+ # becomes ['-v', '-i', 1, '-x'] and ['five', 'six']
47
+ # Boolean options, such as -v, must be specified in the optioner definition
48
+ def parse_args(args=[])
49
+ i=0
50
+ while i < args.length
51
+ if boolean_args.include?(args[i])
52
+ flagged_args << args[i]
53
+ else
54
+ if args[i][0].chr == "-"
55
+ flagged_args << args[i]
56
+ flagged_args << args[i+1] if (args[i+1] and !args[i+1].nil?)
57
+ i+=1
58
+ else
59
+ unflagged_args << args[i]
60
+ end
61
+ end
62
+ i+=1
63
+ end
64
+ args
35
65
  end
36
66
 
37
67
  def parent
@@ -356,6 +356,9 @@ fi
356
356
 
357
357
  cp #{Base.remote_storage_path}/#{Base.template_directory}/puppetrerun /usr/bin/puppetrerun
358
358
  chmod +x /usr/bin/puppetrerun
359
+
360
+ cp #{Base.remote_storage_path}/#{Base.template_directory}/puppetcleaner /usr/bin/puppetcleaner
361
+ chmod +x /usr/bin/puppetcleaner
359
362
  EOS
360
363
  end
361
364
  end
@@ -24,7 +24,6 @@ module PoolParty
24
24
  setup_fileserver,
25
25
  setup_autosigning,
26
26
  install_poolparty,
27
- setup_poolparty,
28
27
  restart_puppetmaster,
29
28
  run_first_time,
30
29
  create_local_node,
@@ -35,6 +34,7 @@ module PoolParty
35
34
  [
36
35
  create_local_node,
37
36
  move_templates,
37
+ setup_poolparty,
38
38
  create_poolparty_manifest,
39
39
  restart_puppetd
40
40
  ]
@@ -91,7 +91,7 @@ echo "*" > /etc/puppet/autosign.conf
91
91
  <<-EOS
92
92
  echo "Setting the poolparty configuration"
93
93
  cp #{Base.remote_storage_path}/#{Base.key_file_locations.first} "#{Base.base_config_directory}/.ppkeys"
94
- cp #{Base.remote_storage_path}/#{Base.default_specfile_name} #{Base.base_config_directory}/#{Base.default_specfile_name}
94
+ mv #{Base.remote_storage_path}/#{Base.default_specfile_name} #{Base.base_config_directory}/
95
95
  EOS
96
96
  end
97
97
 
@@ -180,9 +180,11 @@ cp #{Base.remote_storage_path}/poolparty.pp /etc/puppet/manifests/classes/poolpa
180
180
  end
181
181
 
182
182
  def restart_puppetd
183
+ # /usr/bin/puppetrerun
183
184
  <<-EOS
184
185
  echo "Running puppet manifest"
185
- /usr/bin/puppetrerun
186
+ /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
187
+ /usr/bin/puppetcleaner master
186
188
  EOS
187
189
  end
188
190
  end
@@ -5,8 +5,8 @@ module PoolParty
5
5
  ebs_volume_id id
6
6
  ebs_volume_mount_point loc
7
7
  ebs_volume_device "/dev/#{id.sanitize}"
8
-
9
- has_mount(:name => loc, :device => ebs_volume_device, :requires => get_directory(loc))
8
+
9
+ has_mount(:name => loc, :device => ebs_volume_device, :onlyif => "test -d #{loc}")
10
10
  has_directory(:name => loc)
11
11
  end
12
12
 
@@ -23,11 +23,17 @@ module PoolParty
23
23
  self.run_in_context @stored_block if @stored_block
24
24
  end
25
25
 
26
- # Set instances with a range
27
- def instances(arg)
28
- if arg.is_a?(Range)
26
+ # Set instances with a range or a number
27
+ def instances(arg)
28
+ case arg
29
+ when Range
29
30
  minimum_instances arg.first
30
31
  maximum_instances arg.last
32
+ when Fixnum
33
+ minimum_instances arg
34
+ maximum_instances arg
35
+ else
36
+ raise SpecException.new("Don't know how to handle instances cloud input #{arg}")
31
37
  end
32
38
  end
33
39
 
@@ -8,8 +8,8 @@ module PoolParty
8
8
 
9
9
  def using(t)
10
10
  @cloud = self
11
- if available_bases.include?(t.to_sym)
12
- unless using_remoter? || t.nil?
11
+ if t && available_bases.include?(t.to_sym)
12
+ unless using_remoter?
13
13
  self.class.send :attr_reader, :remote_base
14
14
  self.class.send :attr_reader, :parent_cloud
15
15
  mod = "#{t}".preserved_module_constant
@@ -117,8 +117,8 @@ begin
117
117
 
118
118
  def before_configuration_tasks
119
119
  if has_cert_and_key?
120
- copy_file_to_storage_directory(pub_key)
121
- copy_file_to_storage_directory(private_key)
120
+ # copy_file_to_storage_directory(pub_key)
121
+ # copy_file_to_storage_directory(private_key)
122
122
  end
123
123
  end
124
124
  def has_cert_and_key?
@@ -140,8 +140,8 @@ begin
140
140
  def custom_install_tasks_for(o)
141
141
  arr = if has_cert_and_key?
142
142
  [
143
- "mv #{::File.basename(pub_key)} #{Base.base_config_directory}/ssl/public_keys/#{o.name}.pem",
144
- "mv #{::File.basename(private_key)} #{Base.base_config_directory}/ssl/private_keys/#{o.name}.pem"
143
+ # "mv #{::File.basename(pub_key)} #{Base.base_config_directory}/ssl/public_keys/#{o.name}.pem",
144
+ # "mv #{::File.basename(private_key)} #{Base.base_config_directory}/ssl/private_keys/#{o.name}.pem"
145
145
  ]
146
146
  else
147
147
  []
@@ -7,9 +7,14 @@ require File.dirname(__FILE__) + "/../helpers/provisioner_base"
7
7
  module PoolParty
8
8
  module Remote
9
9
  module Remoter
10
- def rsync_storage_files_to_command(remote_instance)
10
+ def rsync_storage_files_to_command(remote_instance)
11
+ #TODO: rsync_to_command("#{Base.storage_directory}/", Base.remote_storage_path, remote_storage_path) if remote_instance
11
12
  "#{rsync_command} #{Base.storage_directory}/ #{remote_instance.ip}:#{Base.remote_storage_path}" if remote_instance
12
13
  end
14
+ # rsync a file to a node. By default to the master node.
15
+ def rsync_to_command(source, target=source, remote_instance=master)
16
+ "#{rsync_command} #{source} #{remote_instance.ip}:#{target}"
17
+ end
13
18
  def run_command_on_command(cmd="ls -l", remote_instance=nil)
14
19
  vputs "Running #{cmd} on #{remote_instance.name == %x[hostname].chomp ? "self (master)" : "#{remote_instance.name}"}"
15
20
  remote_instance.name == %x[hostname].chomp ? %x[#{cmd}] : "#{ssh_command(remote_instance)} '#{cmd}'"
@@ -40,6 +45,13 @@ module PoolParty
40
45
  def remote_rsync_command
41
46
  "rsync -azP --exclude cache -e '#{remote_ssh_string}'"
42
47
  end
48
+
49
+
50
+ # def scp_command(source, dest=target, remote_instance=master)
51
+ # #TODO: check if source is Directory and add -r if it is
52
+ # "scp #{source} #{remote_instance.ip}:#{dest} #{ssh_array.join(' ')}"
53
+ # end
54
+
43
55
  # Get the names of the nodes. Mainly used for puppet templating
44
56
  def list_of_node_names(options={})
45
57
  list_of_running_instances.collect {|ri| ri.name }
@@ -71,10 +83,22 @@ module PoolParty
71
83
  def minimum_number_of_instances_are_running?
72
84
  list_of_running_instances.size >= minimum_instances.to_i
73
85
  end
86
+ # Are the minimum number of instances NOT running?
87
+ def minimum_number_of_instances_are_not_running?
88
+ !(minimum_number_of_instances_are_running?)
89
+ end
74
90
  # Can we shutdown an instance?
75
91
  def can_shutdown_an_instance?
76
92
  list_of_running_instances.size > minimum_instances.to_i
77
93
  end
94
+ # Are too few instances running?
95
+ def are_too_few_instances_running?
96
+ list_of_running_instances.size < minimum_instances.to_i
97
+ end
98
+ # Are there more instances than allowed?
99
+ def are_too_many_instances_running?
100
+ list_of_running_instances.size > maximum_instances.to_i
101
+ end
78
102
  # Request to launch a number of instances
79
103
  def request_launch_new_instances(num=1)
80
104
  out = []
@@ -204,11 +228,17 @@ module PoolParty
204
228
  end
205
229
  # Stub method for the time being to handle expansion of the cloud
206
230
  def should_expand_cloud?(force=false)
207
- valid_rules?(:expand_when) || force || false
231
+ (are_too_few_instances_running? || are_expansion_rules_valid? ) || force || false
232
+ end
233
+ def are_expansion_rules_valid?
234
+ valid_rules?(:expand_when)
208
235
  end
209
236
  # Stub method for the time being to handle the contraction of the cloud
210
237
  def should_contract_cloud?(force=false)
211
- valid_rules?(:contract_when) || force || false
238
+ (are_too_many_instances_running? || are_contraction_rules_valid?) || force || false
239
+ end
240
+ def are_contraction_rules_valid?
241
+ valid_rules?(:contract_when)
212
242
  end
213
243
  # Expand the cloud
214
244
  # If we can start a new instance and the load requires us to expand
@@ -233,12 +263,10 @@ module PoolParty
233
263
  # If we can shutdown an instnace and the load allows us to contract
234
264
  # the cloud, then we should request_termination_of_non_master_instance
235
265
  def contract_cloud_if_necessary(force=false)
236
- if can_shutdown_an_instance?
237
- if should_contract_cloud?(force)
238
- vputs "Shrinking the cloud by 1"
239
- before_shutdown
240
- request_termination_of_non_master_instance
241
- end
266
+ if can_shutdown_an_instance? && should_contract_cloud?(force)
267
+ vputs "Shrinking the cloud by 1"
268
+ before_shutdown
269
+ request_termination_of_non_master_instance
242
270
  end
243
271
  end
244
272
 
@@ -254,6 +282,13 @@ module PoolParty
254
282
  def before_shutdown
255
283
  end
256
284
 
285
+ # Rsync a file or directory to a node. Rsync to master by default
286
+ def rsync_to(source, target=source, num=0)
287
+ str = "#{rsync_to_command(source, target, get_instance_by_number( num ))}"
288
+ vputs "Running: #{str}"
289
+ verbose ? Kernel.system(str) : hide_output {Kernel.system str}
290
+ end
291
+
257
292
  # Rsync command to the instance
258
293
  def rsync_storage_files_to(instance=nil)
259
294
  hide_output {Kernel.system "#{rsync_storage_files_to_command(instance)}" if instance}
@@ -7,9 +7,15 @@ if [ $(/usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server mast
7
7
  echo "Clearing old certs"
8
8
  HN=`hostname`
9
9
  if [[ $HN == "master" ]]; then
10
- ps aux | grep puppetmaster | awk '{print $2}' | xargs kill;rm -rf /etc/poolparty/ssl;/etc/init.d/puppetmaster start
11
- /etc/init.d/puppetmaster start && /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
10
+ rm /etc/poolparty/ssl/ca/signed/$HN*
11
+ if [ $(/usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master) ]; then
12
+ echo "Run successfully" && exit 0
13
+ else
14
+ /etc/init.d/puppetmaster stop;rm -rf /etc/poolparty/ssl;/etc/init.d/puppetmaster start
15
+ /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
16
+ fi
12
17
  else
13
- rm -rf /etc/poolparty/ssl/*;/usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
18
+ rm /etc/poolparty/ssl/ca/signed/$HN*
19
+ /usr/sbin/puppetd --onetime --no-daemonize --logdest syslog --server master
14
20
  fi
15
21
  fi
@@ -2,7 +2,7 @@ module PoolParty
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
- TINY = 78
5
+ TINY = 79
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/poolparty.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poolparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.78
4
+ version: 0.2.79
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ari Lerner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-05 00:00:00 -08:00
12
+ date: 2008-12-06 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -68,6 +68,7 @@ executables:
68
68
  - cloud-osxcopy
69
69
  - cloud-provision
70
70
  - cloud-refresh
71
+ - cloud-rsync
71
72
  - cloud-run
72
73
  - cloud-ssh
73
74
  - cloud-start
@@ -127,6 +128,7 @@ files:
127
128
  - bin/cloud-osxcopy
128
129
  - bin/cloud-provision
129
130
  - bin/cloud-refresh
131
+ - bin/cloud-rsync
130
132
  - bin/cloud-run
131
133
  - bin/cloud-ssh
132
134
  - bin/cloud-start
@@ -192,6 +194,7 @@ files:
192
194
  - lib/erlang/messenger/ebin/pm_node_rel-0.1.rel
193
195
  - lib/erlang/messenger/ebin/pm_node_supervisor.beam
194
196
  - lib/erlang/messenger/ebin/pm_packager.beam
197
+ - lib/erlang/messenger/ebin/pm_spawner.beam
195
198
  - lib/erlang/messenger/ebin/pm_strings.beam
196
199
  - lib/erlang/messenger/ebin/utils.beam
197
200
  - lib/erlang/messenger/include/defines.hrl
@@ -271,6 +274,7 @@ files:
271
274
  - lib/erlang/messenger/src/pm_node.erl
272
275
  - lib/erlang/messenger/src/pm_node_supervisor.erl
273
276
  - lib/erlang/messenger/src/pm_packager.erl
277
+ - lib/erlang/messenger/src/pm_spawner.erl
274
278
  - lib/erlang/messenger/src/pm_strings.erl
275
279
  - lib/erlang/messenger/src/utils.erl
276
280
  - lib/erlang/messenger/useful_snippets
@@ -502,7 +506,6 @@ files:
502
506
  - test/test_helper.rb
503
507
  - test/test_pool_spec_generator.rb
504
508
  - test/test_poolparty.rb
505
- - website/index.html
506
509
  - website/index.txt
507
510
  - website/javascripts/rounded_corners_lite.inc.js
508
511
  - website/stylesheets/code.css
@@ -511,7 +514,7 @@ files:
511
514
  has_rdoc: true
512
515
  homepage: http://poolparty.rubyforge.org
513
516
  post_install_message: |-
514
- Get ready to jump in the pool, you just installed PoolParty! (Updated at 09:44 12/05/08)
517
+ Get ready to jump in the pool, you just installed PoolParty! (Updated at 13:46 12/06/08)
515
518
 
516
519
  To get started, run the generator:
517
520
 
@@ -114,9 +114,4 @@ describe "Rules" do
114
114
  @car.y = 5
115
115
  @car.valid_rules?(:names).should == true
116
116
  end
117
- it "should have the rules in an array of hashes" do
118
- @car.names.each do |n|
119
-
120
- end
121
- end
122
117
  end
@@ -1,5 +1,8 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
  require File.dirname(__FILE__) + '/../../../lib/poolparty/helpers/console'
3
+ require File.dirname(__FILE__) + '/../../../lib/poolparty/helpers/binary'
4
+
5
+ reset!
3
6
 
4
7
  describe "Console" do
5
8
  before(:each) do
@@ -27,6 +27,20 @@ describe "Option Parser" do
27
27
  end
28
28
  end
29
29
  end
30
+
31
+ describe "parse_args" do
32
+ before(:each) do
33
+ @op = PoolParty::Optioner.new(%w( -v -i 1 five six -x), {:abstract => true, :parse_options => false})
34
+ end
35
+ it "should have an array of default boolean args" do
36
+ @op.boolean_args.sort.should == ['-V', '-h', '-t', '-v']
37
+ end
38
+ it "should split ARGV into flagged and unflagged arg arrays" do
39
+ @op.unflagged_args.sort.sort.should == ["five", "six"]
40
+ @op.flagged_args.should == ["-v", "-i", "1", "-x"]
41
+ end
42
+ end
43
+
30
44
  it "should be able to take a block and set some options on the block" do
31
45
  PoolParty::Optioner.new(["-w"], {:abstract => false, :load_pools => false}) do |opts, optioner|
32
46
  opts.on('-w', '--wee') { optioner.wee "wee" }
@@ -35,6 +35,11 @@ describe "CloudResourcer" do
35
35
  @tc.instances 4..10
36
36
  @tc.minimum_instances.should == 4
37
37
  end
38
+ it "should be able to accept a Fixnum and set the minimum_instances and maximum_instances" do
39
+ @tc.instances 1
40
+ @tc.minimum_instances.should == 1
41
+ @tc.maximum_instances.should == 1
42
+ end
38
43
  it "should set the max to the maximum instances to the last" do
39
44
  @tc.instances 4..10
40
45
  @tc.maximum_instances.should == 10
@@ -10,17 +10,6 @@ module Hype
10
10
  end
11
11
  register_remote_base :Hype
12
12
  end
13
- class TestClass
14
- include Remote
15
- include RemoterBase
16
-
17
- def keypair
18
- "fake_keypair"
19
- end
20
- def verbose
21
- false
22
- end
23
- end
24
13
 
25
14
  describe "Remote" do
26
15
  before(:each) do
@@ -32,6 +21,9 @@ describe "Remote" do
32
21
  @tc.respond_to?(:using).should == true
33
22
  end
34
23
  it "should include the module with using" do
24
+ @tc.instance_eval do
25
+ @remote_base = nil
26
+ end
35
27
  @tc.should_receive(:extend).with("Hype".preserved_module_constant).once
36
28
  @tc.using :hype
37
29
  end
@@ -59,6 +51,9 @@ describe "Remote" do
59
51
  @tc.using :hype
60
52
  end
61
53
  it "should only include the remote class once" do
54
+ @tc.instance_eval do
55
+ @remote_base = nil
56
+ end
62
57
  @tc.should_receive(:extend).with(Hype).once
63
58
  @tc.using :hype
64
59
  @tc.using :hype
@@ -191,10 +186,6 @@ describe "Remote" do
191
186
  @tc.request_termination_of_non_master_instance
192
187
  end
193
188
  end
194
- describe "should_expand_cloud?" do
195
- end
196
- describe "should_contract_cloud?" do
197
- end
198
189
  describe "expansions" do
199
190
  before(:each) do
200
191
  setup
@@ -1,9 +1,12 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
- include Remote
3
+ class TestRemoteClass
4
+ include CloudResourcer
5
+ include PoolParty::Remote
4
6
 
5
- class TestRemoter
6
- include RemoterBase
7
+ def keypair
8
+ "fake_keypair"
9
+ end
7
10
  end
8
11
 
9
12
  describe "RemoterBase" do
@@ -12,7 +15,7 @@ describe "RemoterBase" do
12
15
  end
13
16
  describe "methods" do
14
17
  before(:each) do
15
- @tr = TestRemoter.new
18
+ @tr = TestRemoteClass.new
16
19
  end
17
20
  %w(launch_new_instance! terminate_instance describe_instance instances_list).each do |method|
18
21
  eval <<-EOE
@@ -22,7 +25,7 @@ describe "RemoterBase" do
22
25
  it "should not raise an exception if #{method} is defined as a method" do
23
26
  lambda {
24
27
  @tr.instance_eval do
25
- def #{method}
28
+ def #{method}
26
29
  end
27
30
  end
28
31
  @tr.#{method}
@@ -32,6 +35,7 @@ describe "RemoterBase" do
32
35
  end
33
36
  describe "lists" do
34
37
  before(:each) do
38
+ @tr = TestClass.new
35
39
  stub_list_of_instances_for(@tr)
36
40
  end
37
41
  it "should gather a list of the running instances" do
@@ -47,7 +51,7 @@ describe "RemoterBase" do
47
51
  @tr.list_of_nonterminated_instances.map {|a| a.name }.should == ["master", "node1", "node3"]
48
52
  end
49
53
  it "should return a list of remote instances" do
50
- @tr.remote_instances_list.first.class.should == RemoteInstance
54
+ @tr.remote_instances_list.first.class.should == PoolParty::Remote::RemoteInstance
51
55
  end
52
56
  describe "by keypairs" do
53
57
  it "should be able to grab all the alist keypairs" do
@@ -74,6 +78,7 @@ describe "RemoterBase" do
74
78
  before(:each) do
75
79
  @master = Object.new
76
80
  @master.stub!(:ip).and_return "192.68.0.1"
81
+ @tr = TestClass.new
77
82
  @tr.stub!(:master).and_return @master
78
83
  end
79
84
  it "should have the method custom_install_tasks" do;@tr.respond_to?(:custom_install_tasks_for).should == true;end
@@ -1,21 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
- include PoolParty::Remote
4
-
5
- def valid_rules?(*args)
6
- false
7
- end
8
-
9
- class TestClass
10
- include CloudResourcer
11
- include Remote
12
- using :ec2
13
- attr_accessor :parent
14
-
15
- def keypair
16
- "fake_keypair"
17
- end
18
- end
19
3
  describe "Remoter" do
20
4
  before(:each) do
21
5
  setup
@@ -92,5 +76,31 @@ describe "Remoter" do
92
76
  @tc.launch_and_configure_master!
93
77
  end
94
78
  end
79
+ describe "expansions and contractions" do
80
+ before(:each) do
81
+ @tc = TestClass.new
82
+ stub_list_from_remote_for @tc # sets the list of instances to 2
83
+ end
84
+ describe "are_too_few_instances_running?" do
85
+ it "should be false if the number of running instances is larger than the minimum instances" do
86
+ @tc.stub!(:minimum_instances).and_return 1
87
+ @tc.are_too_few_instances_running?.should == false
88
+ end
89
+ it "should be true if the number of running instances is smaller than the minimum instances" do
90
+ @tc.stub!(:minimum_instances).and_return 5
91
+ @tc.are_too_few_instances_running?.should == true
92
+ end
93
+ end
94
+ describe "are_too_many_instances_running?" do
95
+ it "should be true if the number of running instances is larger than the maximum instances" do
96
+ @tc.stub!(:maximum_instances).and_return 1
97
+ @tc.are_too_many_instances_running?.should == true
98
+ end
99
+ it "should be false if the number of running instances is smaller than the maximum instances" do
100
+ @tc.stub!(:maximum_instances).and_return 5
101
+ @tc.are_too_many_instances_running?.should == false
102
+ end
103
+ end
104
+ end
95
105
 
96
106
  end
@@ -25,7 +25,7 @@ describe "Pool" do
25
25
  @pool.respond_to?(:cloud).should == true
26
26
  end
27
27
  it "should evaluate the block when creating a new pool" do
28
- Proc.should_receive(:new).once
28
+ Proc.should_receive(:new).at_least(1)
29
29
  Pool.new(:test) do
30
30
  Proc.new {puts "hi"}
31
31
  end
@@ -16,6 +16,22 @@ ENV["POOL_SPEC"] = nil
16
16
  include PoolParty
17
17
  extend PoolParty
18
18
 
19
+ def are_too_many_instances_running?
20
+ end
21
+ def are_too_few_instances_running?
22
+ end
23
+
24
+ class TestClass < PoolParty::Cloud::Cloud
25
+ include CloudResourcer
26
+ attr_accessor :parent
27
+ def initialize(&block)
28
+ super :test_cloud, nil, &block
29
+ end
30
+ def keypair
31
+ "fake_keypair"
32
+ end
33
+ end
34
+
19
35
  def setup
20
36
  PoolParty::Messenger.stub!(:messenger_send!).and_return false
21
37
  end
data/tasks/spec.rake CHANGED
@@ -4,14 +4,13 @@ require 'spec/rake/spectask'
4
4
  task :default => :spec
5
5
 
6
6
  Spec::Rake::SpecTask.new(:spec) do |t|
7
- t.warning =
8
- t.rcov = false
7
+ t.warning = t.rcov = false
9
8
  t.spec_files = Dir["spec/**/*_spec.rb"]
10
9
  end
11
10
 
12
11
  Spec::Rake::SpecTask.new(:spec_v) do |t|
13
12
  t.rcov = true
14
- t.rcov_opts = ['--exclude', 'gems*,spec*']
13
+ t.rcov_opts = ['--exclude', 'gems*,spec*,website*,test*']
15
14
  t.ruby_opts = []
16
15
  t.spec_files = Dir["spec/**/*_spec.rb"]
17
16
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: auser-poolparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.78
4
+ version: 0.2.79
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ari Lerner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-05 00:00:00 -08:00
12
+ date: 2008-12-06 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -68,6 +68,7 @@ executables:
68
68
  - cloud-osxcopy
69
69
  - cloud-provision
70
70
  - cloud-refresh
71
+ - cloud-rsync
71
72
  - cloud-run
72
73
  - cloud-ssh
73
74
  - cloud-start
@@ -127,6 +128,7 @@ files:
127
128
  - bin/cloud-osxcopy
128
129
  - bin/cloud-provision
129
130
  - bin/cloud-refresh
131
+ - bin/cloud-rsync
130
132
  - bin/cloud-run
131
133
  - bin/cloud-ssh
132
134
  - bin/cloud-start
@@ -192,6 +194,7 @@ files:
192
194
  - lib/erlang/messenger/ebin/pm_node_rel-0.1.rel
193
195
  - lib/erlang/messenger/ebin/pm_node_supervisor.beam
194
196
  - lib/erlang/messenger/ebin/pm_packager.beam
197
+ - lib/erlang/messenger/ebin/pm_spawner.beam
195
198
  - lib/erlang/messenger/ebin/pm_strings.beam
196
199
  - lib/erlang/messenger/ebin/utils.beam
197
200
  - lib/erlang/messenger/include/defines.hrl
@@ -271,6 +274,7 @@ files:
271
274
  - lib/erlang/messenger/src/pm_node.erl
272
275
  - lib/erlang/messenger/src/pm_node_supervisor.erl
273
276
  - lib/erlang/messenger/src/pm_packager.erl
277
+ - lib/erlang/messenger/src/pm_spawner.erl
274
278
  - lib/erlang/messenger/src/pm_strings.erl
275
279
  - lib/erlang/messenger/src/utils.erl
276
280
  - lib/erlang/messenger/useful_snippets
@@ -502,7 +506,6 @@ files:
502
506
  - test/test_helper.rb
503
507
  - test/test_pool_spec_generator.rb
504
508
  - test/test_poolparty.rb
505
- - website/index.html
506
509
  - website/index.txt
507
510
  - website/javascripts/rounded_corners_lite.inc.js
508
511
  - website/stylesheets/code.css
@@ -511,7 +514,7 @@ files:
511
514
  has_rdoc: true
512
515
  homepage: http://poolparty.rubyforge.org
513
516
  post_install_message: |-
514
- Get ready to jump in the pool, you just installed PoolParty! (Updated at 09:44 12/05/08)
517
+ Get ready to jump in the pool, you just installed PoolParty! (Updated at 13:46 12/06/08)
515
518
 
516
519
  To get started, run the generator:
517
520
 
data/website/index.html DELETED
@@ -1,107 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
- <head>
5
- <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
- <title>
8
- PoolParty
9
- </title>
10
- <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
- <link href="stylesheets/code.css" media="screen" rel="stylesheet" type="text/css" />
12
- <style>
13
-
14
- </style>
15
- <script type="text/javascript">
16
- window.onload = function() {
17
- settings = {
18
- tl: { radius: 10 },
19
- tr: { radius: 10 },
20
- bl: { radius: 10 },
21
- br: { radius: 10 },
22
- antiAlias: true,
23
- autoPad: true,
24
- validTags: ["div"]
25
- }
26
- var versionBox = new curvyCorners(settings, document.getElementById("version"));
27
- versionBox.applyCornersToAll();
28
- }
29
- </script>
30
- </head>
31
- <body>
32
- <div id="main">
33
-
34
- <h1>PoolParty</h1>
35
- <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/poolparty"; return false'>
36
- <p>Get Version</p>
37
- <a href="http://rubyforge.org/projects/poolparty" class="numbers">0.2.76</a>
38
- </div>
39
- <h1>&#8216;Easy cloud computing&#8217;</h1>
40
- <h2>What</h2>
41
- <p>A self-healing, load-balanced cloud computing solution. Combined with the power of <a href="http://reductivelabs.com/trac/puppet/">Puppet</a>, the <a href="http://www.linux-ha.org/">High Availability</a> project, ruby and erlang, PoolParty makes it easy and fun to set up your cloud! Currently, you can use it with ec2, but it&#8217;s not tied to any particular service. You can use PoolParty to manage and monitor your home network!</p>
42
- <h2>Installing</h2>
43
- <p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="punct">--</span><span class="ident">source</span> <span class="ident">http</span><span class="punct">:/</span><span class="regex"></span><span class="punct">/</span><span class="ident">gems</span><span class="punct">.</span><span class="ident">github</span><span class="punct">.</span><span class="ident">com</span> <span class="ident">auser</span><span class="punct">-</span><span class="ident">poolparty</span></pre></p>
44
- <h2>The basics</h2>
45
- <h2>Demonstration of usage</h2>
46
- <pre>
47
- cloud spec [name]
48
- </pre>
49
- <p>This will create a basic spec for you in the spec directory. Then, write your spec file. There are examples in the repos as well as the one below:</p>
50
- <p><pre class='syntax'>
51
- <span class="comment"># Basic poolparty template with apache plugin</span>
52
- <span class="ident">require</span> <span class="punct">&quot;</span><span class="string">poolparty-apache2-plugin</span><span class="punct">&quot;</span>
53
-
54
- <span class="ident">pool</span> <span class="symbol">:app</span> <span class="keyword">do</span>
55
-
56
- <span class="ident">instances</span> <span class="number">2</span><span class="punct">..</span><span class="number">5</span>
57
- <span class="ident">port</span> <span class="number">80</span>
58
- <span class="ident">ami</span> <span class="punct">&quot;</span><span class="string">ami-1cd73375</span><span class="punct">&quot;</span> <span class="comment"># Alestic Ubuntu AMI</span>
59
-
60
- <span class="ident">cloud</span> <span class="symbol">:app</span> <span class="keyword">do</span>
61
-
62
- <span class="ident">apache</span> <span class="keyword">do</span>
63
- <span class="ident">installed_as_worker</span>
64
-
65
- <span class="ident">has_virtualhost</span> <span class="keyword">do</span>
66
-
67
- <span class="ident">name</span> <span class="punct">&quot;</span><span class="string">poolpartyrb.com</span><span class="punct">&quot;</span>
68
- <span class="ident">listen</span><span class="punct">(&quot;</span><span class="string">8080</span><span class="punct">&quot;)</span>
69
- <span class="ident">virtual_host_entry</span> <span class="punct">::</span><span class="constant">File</span><span class="punct">.</span><span class="ident">join</span><span class="punct">(</span><span class="constant">File</span><span class="punct">.</span><span class="ident">dirname</span><span class="punct">(</span><span class="constant">__FILE__</span><span class="punct">),</span> <span class="punct">&quot;</span><span class="string">templates</span><span class="punct">&quot;,</span> <span class="punct">&quot;</span><span class="string">virtual_host.conf.erb</span><span class="punct">&quot;)</span>
70
-
71
- <span class="ident">has_git</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">poolpartyrepos</span><span class="punct">&quot;,</span> <span class="symbol">:source</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">git://github.com/auser/xnot.org.git</span><span class="punct">&quot;,</span> <span class="symbol">:path</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">/var/www/xnot.org/public</span><span class="punct">&quot;)</span>
72
-
73
- <span class="keyword">end</span>
74
- <span class="keyword">end</span>
75
-
76
- <span class="keyword">end</span>
77
-
78
- <span class="keyword">end</span>
79
- </pre></p>
80
- <h2>Forum</h2>
81
- <p><a href="http://groups.google.com/group/poolpartyrb">http://groups.google.com/group/PoolPartyRb</a></p>
82
- <h2>How to submit patches</h2>
83
- <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
84
- <p>The trunk repository is <code>http://github.com/auser/poolparty</code> for anonymous access.</p>
85
- <p>You can fetch the source from either:</p>
86
- <ul>
87
- <li>github: <a href="http://github.com/auser/PoolParty/tree/master">http://github.com/auser/PoolParty/tree/master</a></li>
88
- </ul>
89
- <pre>git clone git://github.com/auser/poolparty.git</pre>
90
- <h3>Build and test instructions</h3>
91
- <p><pre class='syntax'>cd PoolParty
92
- rake spec
93
- rake install_gem</pre></p>
94
- <h2>License</h2>
95
- <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
96
- <h2>Contact</h2>
97
- <p>Comments are welcome. Send an email to <a href="mailto:ari.lerner@citrusbyte.com">Ari Lerner</a> email via the <a href="http://groups.google.com/group/PoolParty">forum</a></p>
98
- <p class="coda">
99
- <a href="http://blog.citrusbyte.com">Ari Lerner</a> at <a href="http://citrusbyte.com">CitrusByte</a>, 15th October 2008<br>
100
- Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
101
- </p>
102
- </div>
103
-
104
- <!-- insert site tracking codes here, like Google Urchin -->
105
-
106
- </body>
107
- </html>