novafizz 0.0.8

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.
Files changed (4) hide show
  1. data/bin/novawhiz +119 -0
  2. data/bin/nw +119 -0
  3. data/lib/novawhiz.rb +247 -0
  4. metadata +106 -0
data/bin/novawhiz ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+ require 'main'
3
+ require 'novawhiz'
4
+
5
+ Main do
6
+
7
+ def creds
8
+ {
9
+ # for use with openstack
10
+ :username => ENV['OS_USERNAME'],
11
+ :password => ENV['OS_PASSWORD'],
12
+ :authtenant => ENV['OS_TENANT_NAME'],
13
+ :auth_url => ENV['OS_AUTH_URL'],
14
+ :region => ENV['OS_REGION_NAME'],
15
+
16
+ ## for use with hpfog
17
+ #:provider => ENV['PROVIDER'],
18
+ #:hp_account_id => ENV['HP_ACCOUNT_ID'],
19
+ #:hp_secret_key => ENV['HP_SECRET_KEY'],
20
+ #:hp_auth_uri => ENV['HP_AUTH_URI'],
21
+ #:hp_tenant_id => ENV['HP_TENANT_ID'],
22
+ #:hp_avl_zone => ENV['HP_AVL_ZONE']
23
+ }
24
+ end
25
+
26
+ def run
27
+ STDERR.puts "must specify a subcommand. see `#{$0} help`"
28
+ exit 1
29
+ end
30
+
31
+
32
+ mode 'boot' do
33
+ argument('name') { 'node name to ssh into' }
34
+ def run
35
+ args = params.to_options
36
+ opts[:name] = args['name']
37
+ opts[:flavor] ||= 'standard.xsmall'
38
+ opts[:image] ||= /Ubuntu Precise/
39
+ opts[:sec_groups] ||= ['default']
40
+ opts[:key_name] ||= 'default'
41
+ opts[:region] ||= 'az-2.region-a.geo-1'
42
+ raise 'no name provided' if !opts[:name] or opts[:name].empty?
43
+ nw = NovaWhiz.new creds
44
+ nw.cleanup opts[:name]
45
+ node = nw.boot opts
46
+ end
47
+ end
48
+
49
+
50
+ mode 'ssh' do
51
+ argument('name') { 'node name to ssh into' }
52
+
53
+ def run
54
+ opts = params.to_options
55
+ nw = NovaWhiz.new creds
56
+ node = nw.server_by_name opts['name']
57
+ key_path = File.expand_path('~/.ssh/hpcloud-keys/' + creds[:region] +'/'+ node.key_name)
58
+ exec "ssh -i #{key_path} #{nw.default_user node}@#{node.accessipv4} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
59
+ end
60
+ end
61
+
62
+
63
+ mode 'run' do
64
+ argument('name') { 'node name to ssh into' }
65
+ argument('cmd') { 'cmd to execute on remote host' }
66
+
67
+ def run
68
+ opts = params.to_options
69
+
70
+ res = Net::SSH::Simple.sync do
71
+ nw = NovaWhiz.new creds
72
+ node = nw.server_by_name opts['name']
73
+ raise "VM with name '#{opts['name']}' could not found" if node == nil
74
+
75
+ key = nw.get_key(opts['name'])
76
+ command_in = opts['cmd'] +"\n"
77
+
78
+ ssh(node.accessipv4,
79
+ '/bin/sh',
80
+ :user => 'ubuntu',
81
+ :key_data => [key],
82
+ :timeout => 3600,
83
+ :global_known_hosts_file => ['/dev/null'],
84
+ :user_known_hosts_file => ['/dev/null']) do |e,c,d|
85
+ case e
86
+ when :start
87
+ c.send_data(command_in)
88
+ c.eof!
89
+ when :stdout
90
+ # read the input line-wise (it *will* arrive fragmented!)
91
+ (@buf ||= '') << d
92
+ while line = @buf.slice!(/(.*)\r?\n/)
93
+ yield line.chomp if block_given?
94
+ end
95
+ when :stderr
96
+ (@buf ||= '') << d
97
+ while line = @buf.slice!(/(.*)\r?\n/)
98
+ yield line.chomp if block_given?
99
+ end
100
+ end
101
+ end
102
+ end
103
+ if res.exit_code != 0
104
+ raise "command #{opts['cmd']} failed on XXXX:\n#{res.stdout}\n#{res.stderr}"
105
+ end
106
+ STDOUT.puts res.stdout
107
+ res
108
+ end
109
+ end
110
+
111
+
112
+ #mode 'test' do
113
+ # def run
114
+ # nw = NovaWhiz.new creds
115
+ # nw.fog_test_method
116
+ # end
117
+ #end
118
+
119
+ end
data/bin/nw ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+ require 'main'
3
+ require 'novawhiz'
4
+
5
+ Main do
6
+
7
+ def creds
8
+ {
9
+ # for use with openstack
10
+ :username => ENV['OS_USERNAME'],
11
+ :password => ENV['OS_PASSWORD'],
12
+ :authtenant => ENV['OS_TENANT_NAME'],
13
+ :auth_url => ENV['OS_AUTH_URL'],
14
+ :region => ENV['OS_REGION_NAME'],
15
+
16
+ ## for use with hpfog
17
+ #:provider => ENV['PROVIDER'],
18
+ #:hp_account_id => ENV['HP_ACCOUNT_ID'],
19
+ #:hp_secret_key => ENV['HP_SECRET_KEY'],
20
+ #:hp_auth_uri => ENV['HP_AUTH_URI'],
21
+ #:hp_tenant_id => ENV['HP_TENANT_ID'],
22
+ #:hp_avl_zone => ENV['HP_AVL_ZONE']
23
+ }
24
+ end
25
+
26
+ def run
27
+ STDERR.puts "must specify a subcommand. see `#{$0} help`"
28
+ exit 1
29
+ end
30
+
31
+
32
+ mode 'boot' do
33
+ argument('name') { 'node name to ssh into' }
34
+ def run
35
+ args = params.to_options
36
+ opts[:name] = args['name']
37
+ opts[:flavor] ||= 'standard.xsmall'
38
+ opts[:image] ||= /Ubuntu Precise/
39
+ opts[:sec_groups] ||= ['default']
40
+ opts[:key_name] ||= 'default'
41
+ opts[:region] ||= 'az-2.region-a.geo-1'
42
+ raise 'no name provided' if !opts[:name] or opts[:name].empty?
43
+ nw = NovaWhiz.new creds
44
+ nw.cleanup opts[:name]
45
+ node = nw.boot opts
46
+ end
47
+ end
48
+
49
+
50
+ mode 'ssh' do
51
+ argument('name') { 'node name to ssh into' }
52
+
53
+ def run
54
+ opts = params.to_options
55
+ nw = NovaWhiz.new creds
56
+ node = nw.server_by_name opts['name']
57
+ key_path = File.expand_path('~/.ssh/hpcloud-keys/' + creds[:region] +'/'+ node.key_name)
58
+ exec "ssh -i #{key_path} #{nw.default_user node}@#{node.accessipv4} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
59
+ end
60
+ end
61
+
62
+
63
+ mode 'run' do
64
+ argument('name') { 'node name to ssh into' }
65
+ argument('cmd') { 'cmd to execute on remote host' }
66
+
67
+ def run
68
+ opts = params.to_options
69
+
70
+ res = Net::SSH::Simple.sync do
71
+ nw = NovaWhiz.new creds
72
+ node = nw.server_by_name opts['name']
73
+ raise "VM with name '#{opts['name']}' could not found" if node == nil
74
+
75
+ key = nw.get_key(opts['name'])
76
+ command_in = opts['cmd'] +"\n"
77
+
78
+ ssh(node.accessipv4,
79
+ '/bin/sh',
80
+ :user => 'ubuntu',
81
+ :key_data => [key],
82
+ :timeout => 3600,
83
+ :global_known_hosts_file => ['/dev/null'],
84
+ :user_known_hosts_file => ['/dev/null']) do |e,c,d|
85
+ case e
86
+ when :start
87
+ c.send_data(command_in)
88
+ c.eof!
89
+ when :stdout
90
+ # read the input line-wise (it *will* arrive fragmented!)
91
+ (@buf ||= '') << d
92
+ while line = @buf.slice!(/(.*)\r?\n/)
93
+ yield line.chomp if block_given?
94
+ end
95
+ when :stderr
96
+ (@buf ||= '') << d
97
+ while line = @buf.slice!(/(.*)\r?\n/)
98
+ yield line.chomp if block_given?
99
+ end
100
+ end
101
+ end
102
+ end
103
+ if res.exit_code != 0
104
+ raise "command #{opts['cmd']} failed on XXXX:\n#{res.stdout}\n#{res.stderr}"
105
+ end
106
+ STDOUT.puts res.stdout
107
+ res
108
+ end
109
+ end
110
+
111
+
112
+ #mode 'test' do
113
+ # def run
114
+ # nw = NovaWhiz.new creds
115
+ # nw.fog_test_method
116
+ # end
117
+ #end
118
+
119
+ end
data/lib/novawhiz.rb ADDED
@@ -0,0 +1,247 @@
1
+ require 'openstack'
2
+ require 'net/ssh/simple'
3
+ require 'fileutils'
4
+
5
+ class NovaWhiz
6
+
7
+ attr_accessor :os
8
+
9
+ def initialize(opts)
10
+ @os = OpenStack::Connection.create(
11
+ :username => opts[:username],
12
+ :api_key => opts[:password],
13
+ :authtenant => opts[:authtenant],
14
+ :auth_url => opts[:auth_url],
15
+ :region => opts[:region],
16
+ :service_type => "compute")
17
+
18
+ #@fog = Fog::Compute.new(
19
+ # :provider => opts[:provider],
20
+ # :hp_account_id => opts[:hp_account_id],
21
+ # :hp_secret_key => opts[:hp_secret_key],
22
+ # :hp_auth_uri => opts[:hp_auth_uri],
23
+ # :hp_tenant_id => opts[:hp_tenant_id],
24
+ # :hp_avl_zone => opts[:hp_avl_zone])
25
+ end
26
+
27
+ ## fog methods
28
+ #
29
+ #def fog_test_method()
30
+ #
31
+ # servers = @fog.servers
32
+ # servers.size # returns no. of servers
33
+ # # display servers in a tabular format
34
+ # @fog.servers.table([:id, :name, :state, :created_at])
35
+ # @fog.addresses.table([:id, :ip, :fixed_ip, :instance_id])
36
+ #
37
+ # floatip_id = address_by_ip("15.185.164.224")
38
+ #
39
+ #end
40
+ #
41
+ #def assign_floating_ip(server_name,ip)
42
+ #
43
+ # address = address_by_ip(ip)
44
+ # server = server_by_name(server_name)
45
+ # address.server = server
46
+ # address.instance_id
47
+ #
48
+ #end
49
+ #
50
+ #def server_by_name(name)
51
+ # @fog.server.each do |s|
52
+ # return s if s.name == name
53
+ # end
54
+ # raise "Could not find server with name: #{name}"
55
+ #end
56
+ #
57
+ #def address_by_ip(ip)
58
+ # @fog.addresses.each do |f|
59
+ # return f if f.ip == ip
60
+ # end
61
+ # raise "Could not find id of floating IP: #{ip}"
62
+ #end
63
+ #
64
+ #def address_by_instance_id(instance_id)
65
+ # @fog.addresses.each do |f|
66
+ # return f if f.instance_id == instance_id
67
+ # end
68
+ # raise "Could not find ID of floating IP using instance ID: #{instance_id}"
69
+ #end
70
+ ## end fog methods
71
+
72
+
73
+ def flavor_id(name)
74
+ flavors = @os.flavors.select { |f| f[:name] == name }
75
+ raise "ambiguous/unknown flavor: #{name}" unless flavors.length == 1
76
+ flavors.first[:id]
77
+ end
78
+
79
+ def image_id(reg)
80
+ images = @os.images.select { |i| i[:name] =~ reg }
81
+ raise "ambiguous/unknown image: #{reg} : #{images.inspect}" unless images.length >= 1
82
+ images.first[:id]
83
+ end
84
+
85
+ def replace_period_with_dash(name)
86
+ # bugbug - handle hp cloud bug where key names with two "." can't be deleted.
87
+ # when writing and reading keys, convert "." to "-".
88
+ # remove this code when this openstack bug is fixed
89
+ nameclean = name.gsub(".","-")
90
+ return nameclean
91
+ end
92
+
93
+ def new_key(name)
94
+ key = @os.create_keypair :name => replace_period_with_dash(name)
95
+ key
96
+ end
97
+
98
+ def get_key(key_name, key_dir = File.expand_path('~/.ssh/hpcloud-keys/az-2.region-a.geo-1/'))
99
+ key = ""
100
+ File.open(key_dir + "/" + replace_period_with_dash(key_name), 'r') do |f|
101
+ while line = f.gets
102
+ key+=line
103
+ end
104
+ end
105
+ return key
106
+ end
107
+
108
+ def write_key(key, key_dir = File.expand_path('~/.ssh/hpcloud-keys/az-2.region-a.geo-1/'))
109
+ begin
110
+ FileUtils.mkdir_p(key_dir) unless File.exists?(key_dir)
111
+ keyfile_path = key_dir + "/" + key[:name]
112
+ File.open(keyfile_path, "w") do |f|
113
+ f.write(key[:private_key])
114
+ f.close
115
+ end
116
+ File.chmod(0600,keyfile_path)
117
+ rescue
118
+ raise "Error with writing key at: #{keyfile_path}"
119
+ end
120
+ end
121
+
122
+ def public_ip(server)
123
+ server.accessipv4
124
+ end
125
+
126
+ def wait(timeout, interval=10)
127
+ while timeout > 0 do
128
+ return if yield
129
+ sleep interval
130
+ timeout -= interval
131
+ end
132
+ end
133
+
134
+ def server_by_name(name)
135
+ @os.servers.each do |s|
136
+ return @os.server(s[:id]) if s[:name] == name
137
+ end
138
+ nil
139
+ end
140
+
141
+ def server_list()
142
+ return @os.servers
143
+ end
144
+
145
+ def keypair_name(server)
146
+ server.key_name
147
+ end
148
+
149
+ def default_user(node)
150
+ 'ubuntu'
151
+ end
152
+
153
+ def cleanup(name)
154
+ if server_exists name
155
+ delete_if_exists(name)
156
+ end
157
+
158
+ if keypair_exists name
159
+ delete_keypair_if_exists(name)
160
+ end
161
+
162
+ #TODO: need consistent way of deciding that cleanup is complete. sleep for now.
163
+ sleep(20)
164
+ end
165
+
166
+ def keypair_exists(name)
167
+ kp_names = @os.keypairs.values.map { |v| v[:name] }
168
+ return true if kp_names.include? name
169
+ end
170
+
171
+ def server_exists(name)
172
+ s = server_by_name name
173
+ return true if s
174
+ end
175
+
176
+ def delete_keypair_if_exists(name)
177
+ @os.delete_keypair name if keypair_exists name
178
+ end
179
+
180
+ def delete_if_exists(name)
181
+ s = server_by_name name
182
+ s.delete! if s
183
+ end
184
+
185
+ def run_command(creds, cmd)
186
+ res = Net::SSH::Simple.sync do
187
+ ssh(creds[:ip], '/bin/sh', :user => creds[:user], :key_data => [creds[:key]], :timeout => 3600, :global_known_hosts_file => ['/dev/null'], :user_known_hosts_file => ['/dev/null']) do |e,c,d|
188
+ case e
189
+ when :start
190
+ c.send_data "#{cmd}\n"
191
+ c.eof!
192
+ when :stdout
193
+ # read the input line-wise (it *will* arrive fragmented!)
194
+ (@buf ||= '') << d
195
+ while line = @buf.slice!(/(.*)\r?\n/)
196
+ yield line.chomp if block_given?
197
+ end
198
+ when :stderr
199
+ (@buf ||= '') << d
200
+ while line = @buf.slice!(/(.*)\r?\n/)
201
+ yield line.chomp if block_given?
202
+ end
203
+ end
204
+ end
205
+ end
206
+ if res.exit_code != 0
207
+ raise "command #{cmd} failed on #{creds[:ip]}:\n#{res.stdout}\n#{res.stderr}"
208
+ end
209
+ res
210
+ end
211
+
212
+ # boot an instance and return creds
213
+ def boot(opts)
214
+ opts[:flavor] ||= 'standard.xsmall'
215
+ opts[:image] ||= /Ubuntu Precise/
216
+ opts[:sec_groups] ||= ['default']
217
+ opts[:key_name] ||= 'default'
218
+ opts[:region] ||= 'az-2.region-a.geo-1'
219
+
220
+ raise 'no name provided' if !opts[:name] or opts[:name].empty?
221
+
222
+ cleanup opts[:name]
223
+ private_key = new_key opts[:name]
224
+ write_key(private_key, File.expand_path('~/.ssh/hpcloud-keys/' + opts[:region] + '/'))
225
+
226
+ server = @os.create_server(
227
+ :imageRef => image_id(opts[:image]),
228
+ :flavorRef => flavor_id(opts[:flavor]),
229
+ :key_name => private_key[:name],
230
+ :security_groups => opts[:sec_groups],
231
+ :name => opts[:name])
232
+
233
+ wait(300) do
234
+ server = @os.server(server.id)
235
+ raise 'error booting vm' if server.status == 'ERROR'
236
+ server.status == 'ACTIVE'
237
+ end
238
+ sleep 60
239
+
240
+ {
241
+ :ip => public_ip(server),
242
+ :user => 'ubuntu',
243
+ :key => private_key[:private_key]
244
+ }
245
+ end
246
+
247
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: novafizz
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.8
6
+ platform: ruby
7
+ authors:
8
+ - tim miller
9
+ - matty rhoades
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-11 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: openstack
17
+ version_requirements: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: !binary |-
22
+ MA==
23
+ none: false
24
+ requirement: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: !binary |-
29
+ MA==
30
+ none: false
31
+ prerelease: false
32
+ type: :runtime
33
+ - !ruby/object:Gem::Dependency
34
+ name: net-ssh-simple
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: !binary |-
40
+ MA==
41
+ none: false
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: !binary |-
47
+ MA==
48
+ none: false
49
+ prerelease: false
50
+ type: :runtime
51
+ - !ruby/object:Gem::Dependency
52
+ name: main
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: !binary |-
58
+ MA==
59
+ none: false
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: !binary |-
65
+ MA==
66
+ none: false
67
+ prerelease: false
68
+ type: :runtime
69
+ description: library and command line tool for simplifying openstack nova operations
70
+ email: none@example.com
71
+ executables:
72
+ - novawhiz
73
+ - nw
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - lib/novawhiz.rb
78
+ - bin/novawhiz
79
+ - bin/nw
80
+ homepage: http://rubygems.org/gems/novawhiz
81
+ licenses: []
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: !binary |-
91
+ MA==
92
+ none: false
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: !binary |-
98
+ MA==
99
+ none: false
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 1.8.24
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: simplify nova operations
106
+ test_files: []