kytoon 1.2.5 → 1.3.0
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/CHANGELOG +11 -0
- data/README.md +8 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/config/server_group_libvirt.json +7 -0
- data/lib/kytoon/providers/libvirt/server_group.rb +50 -4
- data/lib/kytoon/providers/openstack/server_group.rb +149 -28
- data/lib/kytoon/util.rb +6 -0
- metadata +4 -4
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
* Mon Dec 13 2012 Dan Prince <dprince@redhat.com> - 1.3.0
|
|
2
|
+
-OpenStack: Switch to Fog.
|
|
3
|
+
-OpenStack: Add support for automatic floating IP configuration via
|
|
4
|
+
'assign_floating_ip' in server group json files.
|
|
5
|
+
-OpenStack: Add support for security group names.
|
|
6
|
+
-OpenStack: Add endpoint configs for region, service_type, service_name.
|
|
7
|
+
-OpenStack: Configure ssh access within the server group.
|
|
8
|
+
-Libvirt: grep correct dnsmasq leases file (use network name)
|
|
9
|
+
-Libvirt: fix libvirt_use_sudo option (string conversion)
|
|
10
|
+
-Libvirt: Configure ssh access within the server group.
|
|
11
|
+
|
|
1
12
|
* Mon Nov 26 2012 Dan Prince <dprince@redhat.com> - 1.2.5
|
|
2
13
|
- Libvirt: ping test instances to ensure they have IPs before
|
|
3
14
|
trying to configure hosts, etc.
|
data/README.md
CHANGED
|
@@ -25,10 +25,13 @@ Inspired by and based on the Chef VPC Toolkit.
|
|
|
25
25
|
|
|
26
26
|
## Installation
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Quick install on Fedora:
|
|
29
29
|
|
|
30
|
+
yum install -y rubygems ruby-devel gcc gcc-c++ libxslt-devel
|
|
30
31
|
gem install kytoon
|
|
31
32
|
|
|
33
|
+
*NOTE: Kytoon has been tested with Fog 1.8.0+ only (1.9.0 will be required to work with Rackspace's OpenStack Cloud)
|
|
34
|
+
|
|
32
35
|
Create a .kytoon.conf file in your $HOME directory.
|
|
33
36
|
|
|
34
37
|
# The default group type.
|
|
@@ -41,9 +44,13 @@ Create a .kytoon.conf file in your $HOME directory.
|
|
|
41
44
|
openstack_password: <password>
|
|
42
45
|
openstack_network_name: public # Optional: defaults to public
|
|
43
46
|
openstack_keypair_name: < keyname > # Optional: file injection via personalities is the default
|
|
47
|
+
openstack_security_groups: ['', ''] # Optional: Array of security group names
|
|
44
48
|
openstack_ip_type: 4 # IP type (4 or 6): defaults to 4
|
|
45
49
|
openstack_build_timeout: 480 # Server build timeout. Defaults to: 480
|
|
46
50
|
openstack_ping_timeout: 60 # Server build timeout. Defaults to: 60
|
|
51
|
+
openstack_service_name: < name > # Optional: default is None... some clouds have multiple 'compute' services so this may be required
|
|
52
|
+
openstack_service_type: compute # Optional: default is 'compute'
|
|
53
|
+
openstack_region: < region name > # Optional
|
|
47
54
|
|
|
48
55
|
# Libvirt settings
|
|
49
56
|
# Whether commands to create local group should use sudo
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.3.0
|
|
@@ -4,9 +4,16 @@
|
|
|
4
4
|
{
|
|
5
5
|
"hostname": "nova1",
|
|
6
6
|
"memory": "1",
|
|
7
|
+
"original_xml": "/home/dprince/f17.xml",
|
|
8
|
+
"create_cow": "true"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"hostname": "login",
|
|
12
|
+
"memory": "1",
|
|
7
13
|
"gateway": "true",
|
|
8
14
|
"original_xml": "/home/dprince/f17.xml",
|
|
9
15
|
"create_cow": "true"
|
|
10
16
|
}
|
|
17
|
+
|
|
11
18
|
]
|
|
12
19
|
}
|
|
@@ -61,7 +61,7 @@ class ServerGroup
|
|
|
61
61
|
json_hash=JSON.parse(json)
|
|
62
62
|
|
|
63
63
|
configs = Util.load_configs
|
|
64
|
-
use_sudo = ENV['LIBVIRT_USE_SUDO'] || configs['libvirt_use_sudo']
|
|
64
|
+
use_sudo = ENV['LIBVIRT_USE_SUDO'] || configs['libvirt_use_sudo'].to_s
|
|
65
65
|
|
|
66
66
|
sg=ServerGroup.new(
|
|
67
67
|
:id => json_hash["id"],
|
|
@@ -138,11 +138,25 @@ class ServerGroup
|
|
|
138
138
|
end
|
|
139
139
|
out_file=File.join(@@data_dir, "#{@id}.json")
|
|
140
140
|
File.delete(out_file) if File.exists?(out_file)
|
|
141
|
+
|
|
142
|
+
#cleanup ssh keys
|
|
143
|
+
private_ssh_key = File.join(@@data_dir, "#{@id}_id_rsa")
|
|
144
|
+
public_ssh_key = File.join(@@data_dir, "#{@id}_id_rsa.pub")
|
|
145
|
+
[private_ssh_key, public_ssh_key].each do |file|
|
|
146
|
+
File.delete(file) if File.exists?(file)
|
|
147
|
+
end
|
|
148
|
+
|
|
141
149
|
end
|
|
142
150
|
|
|
143
151
|
def self.create(sg)
|
|
144
152
|
|
|
145
153
|
ssh_public_key = Kytoon::Util.load_public_key
|
|
154
|
+
|
|
155
|
+
base_key_name=File.join(@@data_dir, "#{sg.id}_id_rsa")
|
|
156
|
+
Kytoon::Util.generate_ssh_keypair(base_key_name)
|
|
157
|
+
private_ssh_key=IO.read(base_key_name)
|
|
158
|
+
public_ssh_key=IO.read(base_key_name + ".pub")
|
|
159
|
+
|
|
146
160
|
sudo = sg.use_sudo =~ /(true|t|yes|y|1)$/i ? "sudo" : ""
|
|
147
161
|
hosts_file_data = "127.0.0.1\tlocalhost localhost.localdomain\n"
|
|
148
162
|
sg.servers.each do |server|
|
|
@@ -158,6 +172,31 @@ class ServerGroup
|
|
|
158
172
|
end
|
|
159
173
|
|
|
160
174
|
puts "Copying hosts files..."
|
|
175
|
+
|
|
176
|
+
gateway_ssh_config = %{
|
|
177
|
+
[ -d .ssh ] || mkdir .ssh
|
|
178
|
+
cat > .ssh/id_rsa <<-EOF_CAT
|
|
179
|
+
#{private_ssh_key}
|
|
180
|
+
EOF_CAT
|
|
181
|
+
chmod 600 .ssh/id_rsa
|
|
182
|
+
cat > .ssh/id_rsa.pub <<-EOF_CAT
|
|
183
|
+
#{public_ssh_key}
|
|
184
|
+
EOF_CAT
|
|
185
|
+
chmod 600 .ssh/id_rsa.pub
|
|
186
|
+
cat > .ssh/config <<-EOF_CAT
|
|
187
|
+
StrictHostKeyChecking no
|
|
188
|
+
EOF_CAT
|
|
189
|
+
chmod 600 .ssh/config
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
node_ssh_config= %{
|
|
193
|
+
[ -d .ssh ] || mkdir .ssh
|
|
194
|
+
cat > .ssh/authorized_keys <<-EOF_CAT
|
|
195
|
+
#{public_ssh_key}
|
|
196
|
+
EOF_CAT
|
|
197
|
+
chmod 600 .ssh/authorized_keys
|
|
198
|
+
}
|
|
199
|
+
|
|
161
200
|
#now that we have IP info copy hosts files into the servers
|
|
162
201
|
sg.servers.each do |server|
|
|
163
202
|
ping_test(server['ip_address'])
|
|
@@ -169,6 +208,7 @@ hostname "#{server['hostname']}"
|
|
|
169
208
|
if [ -f /etc/sysconfig/network ]; then
|
|
170
209
|
sed -e "s|^HOSTNAME.*|HOSTNAME=#{server['hostname']}|" -i /etc/sysconfig/network
|
|
171
210
|
fi
|
|
211
|
+
#{server['gateway'] == 'true' ? gateway_ssh_config : node_ssh_config}
|
|
172
212
|
}, server['ip_address']) do |ok, out|
|
|
173
213
|
if not ok
|
|
174
214
|
puts out
|
|
@@ -304,7 +344,8 @@ if [ -n "$LV_ROOT" ]; then
|
|
|
304
344
|
mount $LV_ROOT / : \
|
|
305
345
|
sh "/bin/mkdir -p /root/.ssh" : \
|
|
306
346
|
write-append /root/.ssh/authorized_keys "#{ssh_public_key}" : \
|
|
307
|
-
sh "/bin/chmod
|
|
347
|
+
sh "/bin/chmod 700 /root/.ssh" : \
|
|
348
|
+
sh "/bin/chmod 600 /root/.ssh/authorized_keys"
|
|
308
349
|
fi
|
|
309
350
|
|
|
310
351
|
#{sudo} virsh setmaxmem #{domain_name} #{instance_memory}
|
|
@@ -320,17 +361,22 @@ fi
|
|
|
320
361
|
|
|
321
362
|
# lookup server IP here...
|
|
322
363
|
mac_addr = nil
|
|
364
|
+
network_name = nil
|
|
323
365
|
dom_xml = %x{#{sudo} virsh --connect=qemu:///system dumpxml #{domain_name}}
|
|
324
366
|
dom = REXML::Document.new(dom_xml)
|
|
325
367
|
REXML::XPath.each(dom, "//interface/mac") do |interface_xml|
|
|
326
368
|
mac_addr = interface_xml.attributes['address']
|
|
327
369
|
end
|
|
328
370
|
raise KytoonException, "Failed to lookup mac address for #{inst_name}" if mac_addr.nil?
|
|
371
|
+
REXML::XPath.each(dom, "//interface/source") do |interface_xml|
|
|
372
|
+
network_name = interface_xml.attributes['network']
|
|
373
|
+
end
|
|
374
|
+
raise KytoonException, "Failed to lookup network name for #{inst_name}" if network_name.nil?
|
|
329
375
|
|
|
330
|
-
instance_ip = %x{grep -i #{mac_addr} /var/lib/libvirt/dnsmasq
|
|
376
|
+
instance_ip = %x{grep -i #{mac_addr} /var/lib/libvirt/dnsmasq/#{network_name}.leases | cut -d " " -f 3}.chomp
|
|
331
377
|
count = 0
|
|
332
378
|
until not instance_ip.empty? do
|
|
333
|
-
instance_ip = %x{grep -i #{mac_addr} /var/lib/libvirt/dnsmasq
|
|
379
|
+
instance_ip = %x{grep -i #{mac_addr} /var/lib/libvirt/dnsmasq/#{network_name}.leases | cut -d " " -f 3}.chomp
|
|
334
380
|
sleep 1
|
|
335
381
|
count += 1
|
|
336
382
|
if count >= 60 then
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
require 'kytoon/util'
|
|
3
|
-
require '
|
|
3
|
+
require 'fog'
|
|
4
4
|
|
|
5
5
|
module Kytoon
|
|
6
6
|
|
|
@@ -26,10 +26,12 @@ class ServerGroup
|
|
|
26
26
|
|
|
27
27
|
attr_accessor :id
|
|
28
28
|
attr_accessor :name
|
|
29
|
+
attr_accessor :use_security_groups
|
|
29
30
|
|
|
30
31
|
def initialize(options={})
|
|
31
32
|
@id = options[:id] || Time.now.to_f
|
|
32
33
|
@name = options[:name]
|
|
34
|
+
@use_security_groups = options[:use_security_groups]
|
|
33
35
|
@servers=[]
|
|
34
36
|
end
|
|
35
37
|
|
|
@@ -52,7 +54,8 @@ class ServerGroup
|
|
|
52
54
|
|
|
53
55
|
sg=ServerGroup.new(
|
|
54
56
|
:id => json_hash["id"],
|
|
55
|
-
:name => json_hash["name"]
|
|
57
|
+
:name => json_hash["name"],
|
|
58
|
+
:use_security_groups => json_hash["use_security_groups"]
|
|
56
59
|
)
|
|
57
60
|
json_hash["servers"].each do |server_hash|
|
|
58
61
|
|
|
@@ -62,7 +65,11 @@ class ServerGroup
|
|
|
62
65
|
'image_ref' => server_hash['image_ref'],
|
|
63
66
|
'flavor_ref' => server_hash['flavor_ref'],
|
|
64
67
|
'keypair_name' => server_hash['keypair_name'],
|
|
68
|
+
'floating_ip' => server_hash['floating_ip'],
|
|
65
69
|
'gateway' => server_hash['gateway'] || "false",
|
|
70
|
+
'assign_floating_ip' => server_hash['assign_floating_ip'] || "false",
|
|
71
|
+
'floating_ip' => server_hash['floating_ip'] || nil,
|
|
72
|
+
'floating_ip_id' => server_hash['floating_ip_id'] || nil,
|
|
66
73
|
'ip_address' => server_hash['ip_address']
|
|
67
74
|
}
|
|
68
75
|
end
|
|
@@ -84,7 +91,7 @@ class ServerGroup
|
|
|
84
91
|
|
|
85
92
|
def server_names
|
|
86
93
|
|
|
87
|
-
names=[]
|
|
94
|
+
names=[]
|
|
88
95
|
|
|
89
96
|
servers.each do |server|
|
|
90
97
|
if block_given? then
|
|
@@ -103,10 +110,11 @@ class ServerGroup
|
|
|
103
110
|
sg_hash = {
|
|
104
111
|
'id' => @id,
|
|
105
112
|
'name' => @name,
|
|
113
|
+
'use_security_groups' => @use_security_groups,
|
|
106
114
|
'servers' => []
|
|
107
115
|
}
|
|
108
116
|
@servers.each do |server|
|
|
109
|
-
sg_hash['servers'] << {'id' => server['id'], 'hostname' => server['hostname'], 'image_ref' => server['image_ref'], 'gateway' => server['gateway'], 'flavor_ref' => server['flavor_ref'], 'ip_address' => server['ip_address']}
|
|
117
|
+
sg_hash['servers'] << {'id' => server['id'], 'hostname' => server['hostname'], 'image_ref' => server['image_ref'], 'gateway' => server['gateway'], 'flavor_ref' => server['flavor_ref'], 'ip_address' => server['ip_address'], 'floating_ip' => server['floating_ip'], 'floating_ip_id' => server['floating_ip_id'], 'assign_floating_ip' => server['assign_floating_ip']}
|
|
110
118
|
end
|
|
111
119
|
|
|
112
120
|
FileUtils.mkdir_p(@@data_dir)
|
|
@@ -118,23 +126,44 @@ class ServerGroup
|
|
|
118
126
|
|
|
119
127
|
def delete
|
|
120
128
|
servers.each do |server|
|
|
129
|
+
if server['assign_floating_ip'] == 'true' then
|
|
130
|
+
ServerGroup.release_floating_ip(server)
|
|
131
|
+
end
|
|
121
132
|
ServerGroup.destroy_instance(server['id'])
|
|
122
133
|
end
|
|
134
|
+
|
|
135
|
+
#cleanup ssh keys
|
|
136
|
+
private_ssh_key = File.join(@@data_dir, "#{@id}_id_rsa")
|
|
137
|
+
public_ssh_key = File.join(@@data_dir, "#{@id}_id_rsa.pub")
|
|
138
|
+
[private_ssh_key, public_ssh_key].each do |file|
|
|
139
|
+
File.delete(file) if File.exists?(file)
|
|
140
|
+
end
|
|
141
|
+
|
|
123
142
|
out_file=File.join(@@data_dir, "#{@id}.json")
|
|
124
143
|
File.delete(out_file) if File.exists?(out_file)
|
|
125
144
|
end
|
|
126
145
|
|
|
127
|
-
|
|
128
146
|
def self.create(sg)
|
|
129
147
|
|
|
130
148
|
hosts_file_data = "127.0.0.1\tlocalhost localhost.localdomain\n"
|
|
131
149
|
|
|
132
150
|
build_timeout = (Util.load_configs['openstack_build_timeout'] || 60).to_i
|
|
133
151
|
|
|
152
|
+
base_key_name=File.join(@@data_dir, "#{sg.id}_id_rsa")
|
|
153
|
+
Kytoon::Util.generate_ssh_keypair(base_key_name)
|
|
154
|
+
private_ssh_key=IO.read(base_key_name)
|
|
155
|
+
public_ssh_key=IO.read(base_key_name + ".pub")
|
|
156
|
+
|
|
134
157
|
sg.servers.each do |server|
|
|
135
158
|
server_id = create_instance(sg.id, server['hostname'], server['image_ref'], server['flavor_ref'], server['keypair_name']).id
|
|
136
|
-
|
|
137
159
|
server['id'] = server_id
|
|
160
|
+
|
|
161
|
+
if server['assign_floating_ip'] == 'true' then
|
|
162
|
+
floating_data = assign_floating_ip(server_id)
|
|
163
|
+
server['floating_ip_id'] = floating_data[0]
|
|
164
|
+
server['floating_ip'] = floating_data[1]
|
|
165
|
+
end
|
|
166
|
+
|
|
138
167
|
sg.cache_to_disk
|
|
139
168
|
end
|
|
140
169
|
|
|
@@ -143,7 +172,11 @@ class ServerGroup
|
|
|
143
172
|
ips = get_server_ips
|
|
144
173
|
sg.servers.each do |server|
|
|
145
174
|
server_ip = ips[server['id']]
|
|
146
|
-
server['
|
|
175
|
+
if server['assign_floating_ip'] == 'true' then
|
|
176
|
+
server['ip_address'] = server['floating_ip']
|
|
177
|
+
else
|
|
178
|
+
server['ip_address'] = server_ip
|
|
179
|
+
end
|
|
147
180
|
sg.cache_to_disk
|
|
148
181
|
hosts_file_data += "#{server_ip}\t#{server['hostname']}\n"
|
|
149
182
|
end
|
|
@@ -152,9 +185,33 @@ class ServerGroup
|
|
|
152
185
|
raise KytoonException, "Timeout building server group."
|
|
153
186
|
end
|
|
154
187
|
|
|
155
|
-
|
|
156
188
|
puts "Copying hosts files..."
|
|
157
|
-
|
|
189
|
+
|
|
190
|
+
gateway_ssh_config = %{
|
|
191
|
+
[ -d .ssh ] || mkdir .ssh
|
|
192
|
+
cat > .ssh/id_rsa <<-EOF_CAT
|
|
193
|
+
#{private_ssh_key}
|
|
194
|
+
EOF_CAT
|
|
195
|
+
chmod 600 .ssh/id_rsa
|
|
196
|
+
cat > .ssh/id_rsa.pub <<-EOF_CAT
|
|
197
|
+
#{public_ssh_key}
|
|
198
|
+
EOF_CAT
|
|
199
|
+
chmod 600 .ssh/id_rsa.pub
|
|
200
|
+
cat > .ssh/config <<-EOF_CAT
|
|
201
|
+
StrictHostKeyChecking no
|
|
202
|
+
EOF_CAT
|
|
203
|
+
chmod 600 .ssh/config
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
node_ssh_config= %{
|
|
207
|
+
[ -d .ssh ] || mkdir .ssh
|
|
208
|
+
cat > .ssh/authorized_keys <<-EOF_CAT
|
|
209
|
+
#{public_ssh_key}
|
|
210
|
+
EOF_CAT
|
|
211
|
+
chmod 600 .ssh/authorized_keys
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
# now that we have IP info copy hosts files into the servers
|
|
158
215
|
sg.servers.each do |server|
|
|
159
216
|
ping_test(server['ip_address'])
|
|
160
217
|
Kytoon::Util.remote_exec(%{
|
|
@@ -165,6 +222,7 @@ hostname "#{server['hostname']}"
|
|
|
165
222
|
if [ -f /etc/sysconfig/network ]; then
|
|
166
223
|
sed -e "s|^HOSTNAME.*|HOSTNAME=#{server['hostname']}|" -i /etc/sysconfig/network
|
|
167
224
|
fi
|
|
225
|
+
#{server['gateway'] == 'true' ? gateway_ssh_config : node_ssh_config}
|
|
168
226
|
}, server['ip_address']) do |ok, out|
|
|
169
227
|
if not ok
|
|
170
228
|
puts out
|
|
@@ -215,11 +273,15 @@ fi
|
|
|
215
273
|
def self.init_connection
|
|
216
274
|
configs = Util.load_configs
|
|
217
275
|
if @@connection.nil? then
|
|
218
|
-
|
|
219
|
-
:
|
|
220
|
-
:
|
|
221
|
-
:
|
|
222
|
-
:
|
|
276
|
+
@connection = Fog::Compute.new(
|
|
277
|
+
:provider => :openstack,
|
|
278
|
+
:openstack_auth_url => configs['openstack_url'],
|
|
279
|
+
:openstack_username => configs['openstack_username'],
|
|
280
|
+
:openstack_api_key => configs['openstack_password'],
|
|
281
|
+
:openstack_service_name => configs['openstack_service_name'],
|
|
282
|
+
:openstack_service_type => configs['openstack_service_type'],
|
|
283
|
+
:openstack_region => configs['openstack_region']
|
|
284
|
+
)
|
|
223
285
|
else
|
|
224
286
|
@@connection
|
|
225
287
|
end
|
|
@@ -227,24 +289,76 @@ fi
|
|
|
227
289
|
|
|
228
290
|
def self.create_instance(group_id, hostname, image_ref, flavor_ref, keypair_name)
|
|
229
291
|
|
|
230
|
-
ssh_public_key = Util.public_key_path
|
|
231
292
|
configs = Util.load_configs
|
|
232
|
-
|
|
233
293
|
conn = self.init_connection
|
|
234
294
|
|
|
235
295
|
options = {
|
|
236
296
|
:name => "#{group_id}_#{hostname}",
|
|
237
|
-
:
|
|
238
|
-
:
|
|
239
|
-
:personality => {ssh_public_key => "/root/.ssh/authorized_keys"},
|
|
240
|
-
:is_debug => true}
|
|
297
|
+
:image_ref => image_ref,
|
|
298
|
+
:flavor_ref => flavor_ref}
|
|
241
299
|
|
|
242
300
|
keypair_name = configs['openstack_keypair_name'] if keypair_name.nil?
|
|
301
|
+
security_groups = configs['openstack_security_groups']
|
|
302
|
+
if not security_groups.nil? and not security_groups.empty? then
|
|
303
|
+
options.store(:security_groups, security_groups)
|
|
304
|
+
end
|
|
243
305
|
if not keypair_name.nil? and not keypair_name.empty? then
|
|
244
306
|
options.store(:key_name, keypair_name)
|
|
307
|
+
else
|
|
308
|
+
options.store(:personality, [
|
|
309
|
+
{'path' => "/root/.ssh/authorized_keys",
|
|
310
|
+
'contents' => IO.read(Util.public_key_path)}])
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
server = conn.servers.create(options)
|
|
314
|
+
server
|
|
315
|
+
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def self.assign_floating_ip(server_id)
|
|
319
|
+
|
|
320
|
+
conn = self.init_connection
|
|
321
|
+
|
|
322
|
+
data = conn.allocate_address.body
|
|
323
|
+
address_id = data['floating_ip']['id']
|
|
324
|
+
address_ip = data['floating_ip']['ip']
|
|
325
|
+
|
|
326
|
+
configs = Util.load_configs
|
|
327
|
+
network_name = configs['openstack_network_name'] || 'public'
|
|
328
|
+
|
|
329
|
+
# wait for instance to obtain fixed ip
|
|
330
|
+
1.upto(60) do
|
|
331
|
+
server = conn.servers.get(server_id)
|
|
332
|
+
if server.addresses and server.addresses[network_name] and server.addresses[network_name].detect {|a| a['version'] == self.default_ip_type} then
|
|
333
|
+
break
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
conn.associate_address(server_id, address_ip).body
|
|
338
|
+
[address_id, address_ip]
|
|
339
|
+
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def self.release_floating_ip(server)
|
|
343
|
+
|
|
344
|
+
conn = self.init_connection
|
|
345
|
+
|
|
346
|
+
address_ip = server['floating_ip']
|
|
347
|
+
address_id = server['floating_ip_id']
|
|
348
|
+
|
|
349
|
+
conn.disassociate_address(server['id'], address_ip)
|
|
350
|
+
|
|
351
|
+
# wait for address to disassociate (instance_id should be nil)
|
|
352
|
+
1.upto(30) do
|
|
353
|
+
floating_ips = conn.list_all_addresses.body['floating_ips']
|
|
354
|
+
break if floating_ips.detect {|f| f['id'] == address_id and f['instance_id' == nil]}
|
|
245
355
|
end
|
|
246
356
|
|
|
247
|
-
|
|
357
|
+
begin
|
|
358
|
+
conn.release_address(address_id)
|
|
359
|
+
rescue Fog::Compute::OpenStack::NotFound
|
|
360
|
+
puts "Unable to release IP address #{address_ip}: Not Found."
|
|
361
|
+
end
|
|
248
362
|
|
|
249
363
|
end
|
|
250
364
|
|
|
@@ -265,12 +379,14 @@ fi
|
|
|
265
379
|
until all_active do
|
|
266
380
|
all_active = true
|
|
267
381
|
conn.servers.each do |server|
|
|
268
|
-
server
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
382
|
+
if ips[server.id].nil? then
|
|
383
|
+
server = conn.servers.get(server.id)
|
|
384
|
+
if server.state == 'ACTIVE' then
|
|
385
|
+
addresses = server.addresses[network_name].select {|a| a['version'] == self.default_ip_type}
|
|
386
|
+
ips[server.id] = addresses[0]['addr']
|
|
387
|
+
else
|
|
388
|
+
all_active = false
|
|
389
|
+
end
|
|
274
390
|
end
|
|
275
391
|
end
|
|
276
392
|
end
|
|
@@ -302,7 +418,12 @@ fi
|
|
|
302
418
|
def self.destroy_instance(uuid)
|
|
303
419
|
begin
|
|
304
420
|
conn = self.init_connection
|
|
305
|
-
conn.
|
|
421
|
+
server = conn.servers.get(uuid)
|
|
422
|
+
if server then
|
|
423
|
+
server.destroy
|
|
424
|
+
else
|
|
425
|
+
puts "Server #{uuid} no longer exists."
|
|
426
|
+
end
|
|
306
427
|
rescue Exception => e
|
|
307
428
|
puts "Error deleting server: #{e.message}"
|
|
308
429
|
end
|
data/lib/kytoon/util.rb
CHANGED
|
@@ -116,6 +116,12 @@ REMOTE_EXEC_EOF
|
|
|
116
116
|
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
+
# Generate an ssh keypair using the specified base path
|
|
120
|
+
def self.generate_ssh_keypair(ssh_key_basepath)
|
|
121
|
+
FileUtils.mkdir_p(File.dirname(ssh_key_basepath))
|
|
122
|
+
%x{ssh-keygen -N '' -f #{ssh_key_basepath} -t rsa -q}
|
|
123
|
+
end
|
|
124
|
+
|
|
119
125
|
end
|
|
120
126
|
|
|
121
127
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kytoon
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-
|
|
12
|
+
date: 2012-12-13 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rdoc
|
|
@@ -172,7 +172,7 @@ dependencies:
|
|
|
172
172
|
- !ruby/object:Gem::Version
|
|
173
173
|
version: '0'
|
|
174
174
|
- !ruby/object:Gem::Dependency
|
|
175
|
-
name:
|
|
175
|
+
name: fog
|
|
176
176
|
requirement: !ruby/object:Gem::Requirement
|
|
177
177
|
none: false
|
|
178
178
|
requirements:
|
|
@@ -289,7 +289,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
289
289
|
version: '0'
|
|
290
290
|
segments:
|
|
291
291
|
- 0
|
|
292
|
-
hash:
|
|
292
|
+
hash: 3174001929267576694
|
|
293
293
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
294
294
|
none: false
|
|
295
295
|
requirements:
|