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.
- data/bin/novawhiz +119 -0
- data/bin/nw +119 -0
- data/lib/novawhiz.rb +247 -0
- 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: []
|