ssp 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/bin/ssp CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby -rubygems
2
2
 
3
3
  $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
4
4
  require 'ssp/app'
data/lib/ssp/app.rb CHANGED
@@ -2,7 +2,15 @@ require 'thor'
2
2
  require 'thor/group'
3
3
 
4
4
  module SSP
5
+ module ThorExtensions
6
+ def banner(task, namespace = nil, subcommand = false)
7
+ "#{File.basename($0)} #{task.formatted_usage(self, $thor_runner, subcommand)}"
8
+ end
9
+ end
10
+
5
11
  class App < Thor
12
+ extend ThorExtensions
13
+
6
14
  namespace :app
7
15
  map "-T" => :list
8
16
 
@@ -61,6 +69,9 @@ module SSP
61
69
  unless @_commands_initialized
62
70
  Dir[File.join(File.dirname(__FILE__), "application", "*.rb")].each do |command|
63
71
  require(command)
72
+ klass_name = Thor::Util.camel_case(File.basename(command).sub(/\.rb$/, ''))
73
+ klass = SSP::App.const_get(klass_name)
74
+ klass.extend(ThorExtensions)
64
75
  end
65
76
  @_commands_initialized = true
66
77
  end
@@ -24,8 +24,8 @@ class SSP::App::Node < Thor
24
24
  :desc => "Sets the flavor of the server (1: 256MB, 2: 512MB, 3: 1024MB, ...)",
25
25
  :default => 2
26
26
  method_option :image, :aliases => "-i", :type => :numeric,
27
- :desc => "Sets the image to be used (49: Ubuntu 10.04, 4151016: chef-node)",
28
- :default => 4151016
27
+ :desc => "Sets the image to be used (49: Ubuntu 10.04, 4256704: chef-node)",
28
+ :default => 4256704
29
29
  def create(fqdn, *roles)
30
30
  server = connection.servers.new
31
31
 
@@ -110,6 +110,19 @@ validation_client_name "#{chef_config[:validation_client_name]}"
110
110
  ssh.run
111
111
  end
112
112
 
113
+ desc "list", "Lists available servers on Rackspace"
114
+ def list
115
+ server_list = [ ["ID", "Name", "Public IP", "Private IP", "Flavor ID"].map {|t| shell.set_color(t, :bold)} ]
116
+ server_list += connection.servers.all.map do |server|
117
+ [
118
+ server.id.to_s, server.name,
119
+ server.addresses["public"][0], server.addresses["private"][0],
120
+ server.flavor_id.to_s
121
+ ]
122
+ end
123
+ print_table(server_list)
124
+ end
125
+
113
126
  protected
114
127
  def connection
115
128
  @connection ||= Fog::Rackspace::Servers.new(
@@ -0,0 +1,180 @@
1
+ require 'chef/config'
2
+ require 'chef/knife/ssh'
3
+ require 'ssp/config'
4
+
5
+ class SSP::App::OfficeNode < Thor
6
+ namespace :officenode
7
+
8
+ class_option :ssh_user,
9
+ :desc => "The ssh username",
10
+ :default => "root"
11
+
12
+ class_option :ssh_password,
13
+ :desc => "The ssh password",
14
+ :default => SSP::Config[:vanilla][:root_password]
15
+
16
+ class_option :chef_config, :aliases => "-c",
17
+ :desc => "Location of the chef configuration file",
18
+ :default => File.join(ENV['HOME'], '.chef', 'knife.rb')
19
+
20
+
21
+ desc "create FQDN [ROLES...]", "Creates a new chef client on Vanilla"
22
+ method_option :memory, :aliases => "-m", :type => :numeric,
23
+ :desc => "Sets the memory size for the node in MB",
24
+ :default => 512
25
+ method_option :iplastpart, :aliases => "-i", :type => :numeric,
26
+ :desc => "Sets the last part of the node's IP",
27
+ :required => true
28
+ def create(fqdn, *roles)
29
+ ip = "192.168.1.#{options[:iplastpart]}"
30
+ disk_size = options[:memory] * 20 / 1024
31
+ hostname = fqdn.split(".").first
32
+
33
+ # Convert roles array to proper run list
34
+ run_list = roles.map { |r| r =~ /recipe\[(.*)\]/ ? $1 : "role[#{r}]" }
35
+
36
+ # Always include the chef-client role in the run list
37
+ unless run_list.include? "role[chef-client]"
38
+ run_list.unshift "role[chef-client]"
39
+ end
40
+
41
+ vncpass = pwgen
42
+ rootpass = pwgen
43
+
44
+ say_status "Name: ", fqdn, :cyan
45
+ say_status "Memory: ", "#{options[:memory]}MB", :cyan
46
+ say_status "Disk: ", "#{disk_size}GB", :cyan
47
+ say_status "IP: ", ip, :cyan
48
+ say_status "VNC password: ", vncpass, :cyan
49
+ say_status "root password: ", rootpass, :cyan
50
+
51
+ say "\nRequesting server", :magenta
52
+
53
+ command = <<EOH
54
+ bash -c '
55
+ /root/bin/mkdomu.sh -m #{options[:memory]} -d #{disk_size} -v #{vncpass} -p #{rootpass} #{hostname} #{options[:iplastpart]}
56
+ xm create /etc/xen/#{hostname}.cfg
57
+ '
58
+ EOH
59
+
60
+ ssh_run "vanilla", command
61
+
62
+ say "\nServer ready, waiting 15 seconds to bootstrap."
63
+ sleep 15
64
+
65
+ say "\nBootstrapping #{shell.set_color(fqdn, :bold)}..."
66
+
67
+ command = <<EOH
68
+ bash -c '
69
+ mkdir -p /etc/chef
70
+
71
+ (
72
+ cat <<'EOP'
73
+ 127.0.0.1 localhost localhost.localdomain
74
+ #{ip} #{fqdn} #{fqdn.split(".").first}
75
+
76
+ 192.168.1.82 basil basil.secretsaucepartners.com chef.secretsaucepartners.com
77
+ EOP
78
+ ) > /etc/hosts
79
+
80
+ (
81
+ cat <<'EOP'
82
+ #{IO.read(chef_config[:validation_key])}
83
+ EOP
84
+ ) > /tmp/validation.pem
85
+ awk NF /tmp/validation.pem > /etc/chef/validation.pem
86
+ rm /tmp/validation.pem
87
+
88
+ (
89
+ cat <<'EOP'
90
+ log_level :info
91
+ log_location STDOUT
92
+ chef_server_url "#{chef_config[:chef_server_url]}"
93
+ validation_client_name "#{chef_config[:validation_client_name]}"
94
+ EOP
95
+ ) > /etc/chef/client.rb
96
+
97
+ (
98
+ cat <<'EOP'
99
+ #{{ "run_list" => run_list }.to_json}
100
+ EOP
101
+ ) > /etc/chef/first-boot.json
102
+
103
+ apt-get -y update
104
+ apt-get -y upgrade
105
+
106
+ /usr/local/bin/chef-client -j /etc/chef/first-boot.json'
107
+ EOH
108
+
109
+ begin
110
+ ssh_run ip, command, "root", rootpass
111
+ rescue Net::SSH::HostKeyMismatch => key_ex
112
+ key_ex.remember_host!
113
+ retry
114
+ end
115
+ end
116
+
117
+ desc "list", "Lists available servers on Vanilla"
118
+ def list
119
+ ssh_run "vanilla", "xm list"
120
+ end
121
+
122
+
123
+ desc "destroy FQDN", "Removes a chef client and also destorys the Xen guest on Vanilla"
124
+ def destroy(fqdn)
125
+ hostname = fqdn.split(".").first
126
+
127
+ if ask("Are you sure you want to destroy the `#{fqdn}' node? [yes/no]").downcase != "yes"
128
+ raise Thor::Error, "Aborting."
129
+ end
130
+
131
+ command = <<EOH
132
+ bash -c '
133
+ xm shutdown #{hostname}
134
+ sleep 3
135
+ rm /etc/xen/#{hostname}.cfg
136
+ lvremove -f vg/#{hostname}-{root,swap}'
137
+ EOH
138
+
139
+ ssh_run "vanilla", command
140
+
141
+ say %x{knife node delete #{fqdn} -y -c #{options[:chef_config]} 2>/dev/null}
142
+ say %x{knife client delete #{fqdn} -y -c #{options[:chef_config]} 2>/dev/null}
143
+ end
144
+
145
+ protected
146
+ def chef_config
147
+ unless defined?(@_chef_config_loaded)
148
+ Chef::Config.from_file(options[:chef_config])
149
+ @_chef_config_loaded = true
150
+ end
151
+ Chef::Config
152
+ end
153
+
154
+ def ssh_run(host, command, user = options[:ssh_user], pass = options[:ssh_password])
155
+ ssh = Chef::Knife::Ssh.new
156
+ ssh.name_args = [ host, command ]
157
+ ssh.config[:ssh_user] = user
158
+ ssh.config[:password] = pass
159
+ ssh.config[:manual] = true
160
+
161
+ begin
162
+ ssh.run
163
+ rescue Net::SSH::AuthenticationFailed
164
+ unless config[:ssh_password]
165
+ puts "Failed to authenticate #{config[:ssh_user]} - trying password auth"
166
+ ssh = Chef::Knife::Ssh.new
167
+ ssh.name_args = [ host, command ]
168
+ ssh.config[:ssh_user] = user
169
+ ssh.config[:manual] = true
170
+ ssh.config[:password] = ssh.get_password
171
+ ssh.run
172
+ end
173
+ end
174
+ end
175
+
176
+ def pwgen(length = 16)
177
+ chars = (('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a) - %w(i o 0 1 l I O)
178
+ (1..length).collect {|a| chars[rand(chars.size)]}.join
179
+ end
180
+ end
data/lib/ssp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module SSP
2
- VERSION = "0.1"
2
+ VERSION = "0.2"
3
3
  end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ssp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- version: "0.1"
8
+ - 2
9
+ version: "0.2"
10
10
  platform: ruby
11
11
  authors:
12
12
  - !binary |
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-06-30 00:00:00 +02:00
19
+ date: 2010-07-05 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -64,6 +64,7 @@ files:
64
64
  - lib/ssp/app.rb
65
65
  - lib/ssp/application/bags.rb
66
66
  - lib/ssp/application/node.rb
67
+ - lib/ssp/application/office_node.rb
67
68
  - lib/ssp/application/pair.rb
68
69
  - lib/ssp/config.rb
69
70
  - lib/ssp/version.rb