knife-voxel 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,184 @@
1
+ require 'chef/knife/voxel_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class VoxelVoxserversReimage < Knife
6
+ include Knife::VoxelBase
7
+
8
+ deps do
9
+ require 'chef/json_compat'
10
+ require 'chef/knife/bootstrap'
11
+ require 'hapi'
12
+ require 'readline'
13
+
14
+ Chef::Knife::Bootstrap.load_deps
15
+ end
16
+
17
+ banner "knife voxel voxservers reimage DEVICE_ID (options)"
18
+
19
+ option :swap_size,
20
+ :long => "--swap-size SIZE",
21
+ :description => "Swap Partition Size, in GB",
22
+ :default => 4
23
+
24
+ option :image_id,
25
+ :long => "--image-id IMAGE",
26
+ :description => "Image Id to Install",
27
+ :required => true
28
+
29
+ option :hostname,
30
+ :long => "--hostname NAME",
31
+ :description => "The server's hostname",
32
+ :required => true
33
+
34
+ option :chef_node_name,
35
+ :short => "-N NAME",
36
+ :long => "--node-name NAME",
37
+ :description => "The Chef node name for your new node"
38
+
39
+ option :ssh_user,
40
+ :short => "-x USERNAME",
41
+ :long => "--ssh-user USERNAME",
42
+ :description => "The ssh username; default is 'root'",
43
+ :default => "root"
44
+
45
+ option :ssh_password,
46
+ :short => "-P PASSWORD",
47
+ :long => "--ssh-password PASSWORD",
48
+ :description => "The ssh password"
49
+
50
+ option :identity_file,
51
+ :short => "-i IDENTITY_FILE",
52
+ :long => "--identity-file IDENTITY_FILE",
53
+ :description => "The SSH identity file used for authentication"
54
+
55
+ option :prerelease,
56
+ :long => "--prerelease",
57
+ :description => "Install the pre-release chef gems"
58
+
59
+ option :bootstrap_version,
60
+ :long => "--bootstrap-version VERSION",
61
+ :description => "The version of Chef to install",
62
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
63
+
64
+ option :distro,
65
+ :short => "-d DISTRO",
66
+ :long => "--distro DISTRO",
67
+ :description => "Bootstrap a distro using a template; default is 'ubuntu10.04-gems'",
68
+ :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
69
+ :default => "ubuntu10.04-gems"
70
+
71
+ option :template_file,
72
+ :long => "--template-file TEMPLATE",
73
+ :description => "Full path to location of template to use",
74
+ :proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
75
+ :default => false
76
+
77
+ option :run_list,
78
+ :short => "-r RUN_LIST",
79
+ :long => "--run-list RUN_LIST",
80
+ :description => "Comma separated list of roles/recipes to apply",
81
+ :proc => lambda { |o| o.split(/[\s,]+/) },
82
+ :default => []
83
+
84
+ def bootstrap_for_node(device)
85
+ bootstrap = Chef::Knife::Bootstrap.new
86
+
87
+ bootstrap.name_args = [device['ipassignments']['ipassignment'].select { |i| i['type'] == 'frontend' }.first['content']]
88
+ bootstrap.config[:run_list] = config[:run_list]
89
+ bootstrap.config[:ssh_user] = config[:ssh_user] || "root"
90
+ bootstrap.config[:ssh_password] = device['accessmethods']['accessmethod'].select { |a| a['type'] == 'admin' }.first['password']
91
+ bootstrap.config[:identity_file] = config[:identity_file]
92
+ bootstrap.config[:chef_node_name] = config[:chef_node_name] || "d#{device['id']}"
93
+ bootstrap.config[:prerelease] = config[:prerelease]
94
+ bootstrap.config[:bootstrap_version] = config[:bootstrap_version]
95
+ bootstrap.config[:distro] = config[:distro]
96
+ bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
97
+ bootstrap.config[:template_file] = config[:template_file]
98
+ bootstrap.config[:environment] = config[:environment]
99
+ bootstrap
100
+ end
101
+
102
+ def tcp_test_ssh(hostname)
103
+ begin
104
+ tcp_socket = TCPSocket.new(hostname, 22)
105
+ readable = IO.select([tcp_socket], nil, nil, 5)
106
+ if readable
107
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
108
+ yield
109
+ true
110
+ else
111
+ false
112
+ end
113
+ rescue Errno::ETIMEDOUT
114
+ false
115
+ rescue Errno::EPERM
116
+ false
117
+ rescue Errno::ECONNREFUSED
118
+ sleep 2
119
+ false
120
+ rescue Errno::EHOSTUNREACH
121
+ sleep 2
122
+ false
123
+ ensure
124
+ tcp_socket && tcp_socket.close
125
+ end
126
+ end
127
+
128
+ def run
129
+ $stdout.sync = true
130
+
131
+ unless @name_args.empty?
132
+ create = hapi.voxel_voxservers_reimage(
133
+ :device_id => @name_args.first,
134
+ :image_id => config[:image_id],
135
+ :hostname => config[:hostname],
136
+ :swap_space => config[:swap_size]
137
+ )
138
+
139
+ if create['stat'] == "fail"
140
+ ui.error(create['err']['msg'])
141
+ else
142
+ sleep 2
143
+
144
+ device = hapi.voxel_devices_list( :device_id => create['device']['id'], :verbosity => 'extended' )
145
+
146
+ if device['stat'] == "fail"
147
+ ui.error(device['err']['msg'])
148
+ else
149
+ device = device['devices']['device']
150
+
151
+ puts "#{ui.color("Device ID", :cyan)}: #{device['id']}"
152
+ puts "#{ui.color("Name", :cyan)}: #{device['label']}"
153
+ puts "#{ui.color("Image Id", :cyan)}: #{config[:image_id]}"
154
+ puts "#{ui.color("Facility", :cyan)}: #{device['location']['facility']['code']}"
155
+ puts "#{ui.color("Public IP Address", :cyan)}: #{device['ipassignments']['ipassignment'].select { |i| i['type'] == 'frontend' }.first['content']}"
156
+ puts "#{ui.color("Private IP Address", :cyan)}: #{device['ipassignments']['ipassignment'].select { |i| i['type'] == 'backend' }.first['content']}"
157
+ puts "#{ui.color("Root Password", :cyan)}: #{device['accessmethods']['accessmethod'].select { |a| a['type'] == 'admin' }.first['password']}"
158
+
159
+ status = hapi.voxel_voxservers_status( :device_id => device['id'], :verbosity => 'extended' )
160
+
161
+ while %w{ QUEUED IN_PROGRESS }.include?( status['devices']['device']['status'] ) do
162
+ print "."
163
+ status = hapi.voxel_voxservers_status( :device_id => device['id'], :verbosity => 'extended' )
164
+ sleep 10
165
+ end
166
+
167
+ print "\n#{ui.color("Waiting for sshd", :magenta)}"
168
+
169
+ print(".") until tcp_test_ssh(device['ipassignments']['ipassignment'].select { |i| i['type'] == 'frontend' }.first['content']) { sleep @initial_sleep_delay ||= 10; puts("done") }
170
+
171
+ bootstrap_for_node(device).run
172
+
173
+ puts "#{ui.color("Environment", :cyan)}: #{config[:environment] || '_default'}"
174
+ puts "#{ui.color("Run List", :cyan)}: #{config[:run_list].join(', ')}"
175
+ end
176
+ end
177
+ else
178
+ ui.error( "knife voxel voxservers reimage DEVICE_ID (options)" )
179
+ end
180
+ end
181
+
182
+ end
183
+ end
184
+ end
@@ -1,5 +1,5 @@
1
1
  module Knife
2
2
  module Voxel
3
- VERSION = "0.0.5"
3
+ VERSION = "0.0.6"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-voxel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-13 00:00:00.000000000Z
12
+ date: 2011-10-15 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: voxel-hapi
16
- requirement: &14538140 !ruby/object:Gem::Requirement
16
+ requirement: &10910840 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 1.1.10
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *14538140
24
+ version_requirements: *10910840
25
25
  description: Voxel hAPI Support for Chef's knife command
26
26
  email:
27
27
  - jwb@voxel.net
@@ -42,6 +42,7 @@ files:
42
42
  - lib/chef/knife/voxel_voxservers_create.rb
43
43
  - lib/chef/knife/voxel_voxservers_delete.rb
44
44
  - lib/chef/knife/voxel_voxservers_inventory_list.rb
45
+ - lib/chef/knife/voxel_voxservers_reimage.rb
45
46
  - lib/knife-voxel/version.rb
46
47
  homepage: http://api.voxel.net/
47
48
  licenses: []