foreman_xen 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/app/controllers/foreman_xen/snapshots_controller.rb +74 -78
- data/app/helpers/xen_compute_helper.rb +45 -42
- data/app/models/concerns/fog_extensions/xenserver/server.rb +6 -7
- data/app/models/concerns/foreman_xen/host_helper_extensions.rb +40 -17
- data/app/models/foreman_xen/xenserver.rb +113 -153
- data/app/overrides/hosts/show/snapshot_override.html.erb.deface +2 -0
- data/app/overrides/hosts/show/snapshot_override_legacy.html.erb.deface +2 -0
- data/app/views/compute_resources/form/_xenserver.html.erb +2 -2
- data/app/views/compute_resources_vms/form/_hypervisors.html.erb +4 -4
- data/app/views/compute_resources_vms/form/_templates.html.erb +2 -2
- data/app/views/compute_resources_vms/form/_volume.html.erb +1 -1
- data/app/views/compute_resources_vms/form/_xenstore.html.erb +1 -7
- data/app/views/compute_resources_vms/form/xenserver/_base.html.erb +96 -95
- data/app/views/compute_resources_vms/index/_xenserver.html.erb +7 -7
- data/app/views/foreman_xen/snapshots/new.html.erb +14 -14
- data/app/views/foreman_xen/snapshots/show.html.erb +4 -4
- data/config/routes.rb +2 -0
- data/lib/foreman_xen/engine.rb +11 -3
- data/lib/foreman_xen/version.rb +1 -1
- data/lib/foreman_xen/vnc_tunnel.rb +30 -28
- data/test/foreman_xen_test.rb +1 -1
- data/test/test_helper.rb +4 -4
- metadata +20 -6
@@ -1,11 +1,12 @@
|
|
1
1
|
module ForemanXen
|
2
2
|
class Xenserver < ComputeResource
|
3
|
-
|
3
|
+
validates_presence_of :url, :user, :password
|
4
4
|
|
5
5
|
def provided_attributes
|
6
6
|
super.merge(
|
7
|
-
:uuid => :reference,
|
8
|
-
|
7
|
+
{ :uuid => :reference,
|
8
|
+
:mac => :mac
|
9
|
+
})
|
9
10
|
end
|
10
11
|
|
11
12
|
def capabilities
|
@@ -22,8 +23,8 @@ module ForemanXen
|
|
22
23
|
|
23
24
|
# we default to destroy the VM's storage as well.
|
24
25
|
def destroy_vm(ref, args = {})
|
25
|
-
logger.info "destroy_vm: #{ref} #{args}"
|
26
|
-
|
26
|
+
logger.info "destroy_vm: #{ ref } #{ args }"
|
27
|
+
find_vm_by_uuid(ref).destroy
|
27
28
|
rescue ActiveRecord::RecordNotFound
|
28
29
|
true
|
29
30
|
end
|
@@ -38,145 +39,115 @@ module ForemanXen
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def max_memory
|
41
|
-
|
42
|
-
[hypervisor.metrics.memory_total.to_i,
|
42
|
+
xenServerMaxDoc = 128*1024*1024*1024
|
43
|
+
[hypervisor.metrics.memory_total.to_i, xenServerMaxDoc].min
|
43
44
|
rescue => e
|
44
45
|
logger.error "unable to figure out free memory, guessing instead due to:#{e}"
|
45
|
-
16
|
46
|
+
16*1024*1024*1024
|
46
47
|
end
|
47
48
|
|
48
49
|
def test_connection(options = {})
|
49
50
|
super
|
50
|
-
errors[:url].empty?
|
51
|
+
errors[:url].empty? and errors[:user].empty? and errors[:password].empty? and hypervisor
|
51
52
|
rescue => e
|
52
|
-
|
53
|
-
disconnect
|
54
|
-
rescue
|
55
|
-
nil
|
56
|
-
end
|
53
|
+
disconnect rescue nil
|
57
54
|
errors[:base] << e.message
|
58
55
|
end
|
56
|
+
|
57
|
+
def avalable_hypervisors
|
58
|
+
tmps = client.hosts rescue []
|
59
|
+
tmps.sort { |a, b| a.name <=> b.name }
|
60
|
+
end
|
59
61
|
|
60
|
-
def
|
61
|
-
tmps = begin
|
62
|
-
client.hosts
|
63
|
-
rescue
|
64
|
-
[]
|
65
|
-
end
|
66
|
-
tmps.sort { |a, b| a.name <=> b.name }
|
67
|
-
end
|
68
|
-
|
69
|
-
def new_nic(attr = {})
|
62
|
+
def new_nic(attr={})
|
70
63
|
client.networks.new attr
|
71
64
|
end
|
72
65
|
|
73
|
-
def new_volume(attr
|
66
|
+
def new_volume(attr={})
|
74
67
|
client.storage_repositories.new attr
|
75
68
|
end
|
76
69
|
|
77
70
|
def storage_pools
|
78
|
-
|
71
|
+
|
72
|
+
results = Array.new
|
73
|
+
|
74
|
+
storages = client.storage_repositories.select { |sr| sr.type!= 'udev' && sr.type!= 'iso'} rescue []
|
75
|
+
hosts = client.hosts
|
76
|
+
|
77
|
+
storages.each do |sr|
|
78
|
+
subresults = Hash.new()
|
79
|
+
found = 0
|
80
|
+
hosts.each do |host|
|
81
|
+
|
82
|
+
if (sr.reference == host.suspend_image_sr)
|
83
|
+
found = 1
|
84
|
+
subresults[:name] = sr.name
|
85
|
+
subresults[:display_name] = sr.name + '(' + host.hostname + ')'
|
86
|
+
subresults[:uuid] = sr.uuid
|
87
|
+
break
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
if (found==0)
|
93
|
+
subresults[:name] = sr.name
|
94
|
+
subresults[:display_name] = sr.name
|
95
|
+
subresults[:uuid] = sr.uuid
|
96
|
+
end
|
97
|
+
results.push(subresults)
|
98
|
+
end
|
99
|
+
|
100
|
+
results.sort_by!{|item| item[:display_name] }
|
101
|
+
return results
|
79
102
|
|
80
|
-
storages = begin
|
81
|
-
client.storage_repositories.select { |sr| sr.type != 'udev' && sr.type != 'iso' }
|
82
|
-
rescue
|
83
|
-
[]
|
84
|
-
end
|
85
|
-
hosts = client.hosts
|
86
|
-
|
87
|
-
storages.each do |sr|
|
88
|
-
subresults = {}
|
89
|
-
found = 0
|
90
|
-
|
91
|
-
hosts.each do |host|
|
92
|
-
if sr.reference == host.suspend_image_sr
|
93
|
-
found = 1
|
94
|
-
subresults[:name] = sr.name
|
95
|
-
subresults[:display_name] = sr.name + '(' + host.hostname + ')'
|
96
|
-
subresults[:uuid] = sr.uuid
|
97
|
-
break
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
if found == 0
|
102
|
-
subresults[:name] = sr.name
|
103
|
-
subresults[:display_name] = sr.name
|
104
|
-
subresults[:uuid] = sr.uuid
|
105
|
-
end
|
106
|
-
results.push(subresults)
|
107
|
-
end
|
108
|
-
|
109
|
-
results.sort_by! { |item| item[:display_name] }
|
110
|
-
results
|
111
103
|
end
|
112
104
|
|
113
105
|
def interfaces
|
114
|
-
client.interfaces
|
115
|
-
rescue
|
116
|
-
[]
|
106
|
+
client.interfaces rescue []
|
117
107
|
end
|
118
108
|
|
119
109
|
def networks
|
120
|
-
networks =
|
121
|
-
client.networks
|
122
|
-
rescue
|
123
|
-
[]
|
124
|
-
end
|
110
|
+
networks = client.networks rescue []
|
125
111
|
networks.sort { |a, b| a.name <=> b.name }
|
126
112
|
end
|
127
113
|
|
128
114
|
def templates
|
129
|
-
client.servers.templates
|
130
|
-
rescue
|
131
|
-
[]
|
115
|
+
client.servers.templates rescue []
|
132
116
|
end
|
133
117
|
|
134
118
|
def custom_templates
|
135
|
-
tmps =
|
136
|
-
client.servers.custom_templates.select { |t| !t.is_a_snapshot }
|
137
|
-
rescue
|
138
|
-
[]
|
139
|
-
end
|
119
|
+
tmps = client.servers.custom_templates.select { |t| !t.is_a_snapshot } rescue []
|
140
120
|
tmps.sort { |a, b| a.name <=> b.name }
|
141
121
|
end
|
142
122
|
|
143
123
|
def builtin_templates
|
144
|
-
tmps =
|
145
|
-
client.servers.builtin_templates.select { |t| !t.is_a_snapshot }
|
146
|
-
rescue
|
147
|
-
[]
|
148
|
-
end
|
124
|
+
tmps = client.servers.builtin_templates.select { |t| !t.is_a_snapshot } rescue []
|
149
125
|
tmps.sort { |a, b| a.name <=> b.name }
|
150
126
|
end
|
151
127
|
|
152
128
|
def associated_host(vm)
|
153
|
-
associate_by(
|
129
|
+
associate_by("mac", vm.interfaces.map(&:mac))
|
154
130
|
end
|
155
131
|
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
client.servers.templates.select(&:is_a_snapshot)
|
160
|
-
rescue
|
161
|
-
[]
|
132
|
+
def get_snapshots_for_vm(vm)
|
133
|
+
if vm.snapshots.empty?
|
134
|
+
return []
|
162
135
|
end
|
136
|
+
tmps = client.servers.templates.select { |t| t.is_a_snapshot } rescue []
|
163
137
|
retval = []
|
164
|
-
tmps.each do |snapshot|
|
138
|
+
tmps.each do | snapshot |
|
165
139
|
retval << snapshot if vm.snapshots.include?(snapshot.reference)
|
166
140
|
end
|
167
141
|
retval
|
168
142
|
end
|
169
143
|
|
170
|
-
def
|
171
|
-
tmps =
|
172
|
-
client.servers.templates.select(&:is_a_snapshot)
|
173
|
-
rescue
|
174
|
-
[]
|
175
|
-
end
|
144
|
+
def get_snapshots
|
145
|
+
tmps = client.servers.templates.select { |t| t.is_a_snapshot } rescue []
|
176
146
|
tmps.sort { |a, b| a.name <=> b.name }
|
177
147
|
end
|
178
148
|
|
179
|
-
def new_vm(attr
|
149
|
+
def new_vm(attr={})
|
150
|
+
|
180
151
|
test_connection
|
181
152
|
return unless errors.empty?
|
182
153
|
opts = vm_instance_defaults.merge(attr.to_hash).symbolize_keys
|
@@ -190,21 +161,22 @@ module ForemanXen
|
|
190
161
|
end
|
191
162
|
|
192
163
|
def create_vm(args = {})
|
193
|
-
|
164
|
+
|
165
|
+
custom_template_name = args[:custom_template_name]
|
194
166
|
builtin_template_name = args[:builtin_template_name]
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
if builtin_template_name
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
167
|
+
custom_template_name = custom_template_name.to_s
|
168
|
+
builtin_template_name = builtin_template_name.to_s
|
169
|
+
|
170
|
+
if builtin_template_name!= '' and custom_template_name!=''
|
171
|
+
logger.info "custom_template_name: #{ custom_template_name }"
|
172
|
+
logger.info "builtin_template_name: #{ builtin_template_name }"
|
173
|
+
raise 'you can select at most one template type'
|
174
|
+
end
|
203
175
|
begin
|
204
176
|
vm = nil
|
205
|
-
|
206
|
-
|
207
|
-
if custom_template_name != ''
|
177
|
+
logger.info "create_vm(): custom_template_name: #{ custom_template_name }"
|
178
|
+
logger.info "create_vm(): builtin_template_name: #{ builtin_template_name }"
|
179
|
+
if custom_template_name != ''
|
208
180
|
vm = create_vm_from_custom args
|
209
181
|
else
|
210
182
|
vm = create_vm_from_builtin args
|
@@ -228,31 +200,28 @@ module ForemanXen
|
|
228
200
|
end
|
229
201
|
|
230
202
|
def create_vm_from_custom(args)
|
231
|
-
|
203
|
+
|
204
|
+
mem_max = args[:memory_max]
|
232
205
|
mem_min = args[:memory_min]
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
206
|
+
|
207
|
+
if args[:hypervisor_host] != ''
|
208
|
+
host = client.hosts.find { |host| host.name == args[:hypervisor_host] }
|
209
|
+
logger.info "create_vm_from_builtin: host : #{ host.name }"
|
210
|
+
elsif
|
211
|
+
host = client.hosts.first
|
212
|
+
logger.info "create_vm_from_builtin: host : #{ host.name }"
|
213
|
+
end
|
214
|
+
|
215
|
+
raise 'Memory max cannot be lower than Memory min' if mem_min.to_i > mem_max.to_i
|
243
216
|
vm = client.servers.new :name => args[:name],
|
244
|
-
|
217
|
+
:affinity => host,
|
245
218
|
:template_name => args[:custom_template_name]
|
246
219
|
|
247
220
|
vm.save :auto_start => false
|
248
221
|
|
249
222
|
vm.provision
|
250
223
|
|
251
|
-
|
252
|
-
vm.vifs.first.destroy
|
253
|
-
rescue
|
254
|
-
nil
|
255
|
-
end
|
224
|
+
vm.vifs.first.destroy rescue nil
|
256
225
|
|
257
226
|
create_network(vm, args)
|
258
227
|
|
@@ -277,26 +246,27 @@ module ForemanXen
|
|
277
246
|
i = 0
|
278
247
|
disks.each do |vbd|
|
279
248
|
vbd.vdi.set_attribute('name-label', "#{args[:name]}_#{i}")
|
280
|
-
i
|
249
|
+
i+=1
|
281
250
|
end
|
282
251
|
vm
|
283
252
|
end
|
284
253
|
|
285
254
|
def create_vm_from_builtin(args)
|
255
|
+
|
286
256
|
builtin_template_name = args[:builtin_template_name]
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
257
|
+
builtin_template_name = builtin_template_name.to_s
|
258
|
+
|
259
|
+
if args[:hypervisor_host] != ''
|
260
|
+
host = client.hosts.find { |host| host.name == args[:hypervisor_host] }
|
261
|
+
logger.info "create_vm_from_builtin: host : #{ host.name }"
|
262
|
+
elsif
|
263
|
+
host = client.hosts.first
|
264
|
+
logger.info "create_vm_from_builtin: host : #{ host.name }"
|
265
|
+
end
|
296
266
|
|
297
267
|
storage_repository = client.storage_repositories.find { |sr| sr.uuid == "#{args[:VBDs][:sr_uuid]}" }
|
298
268
|
|
299
|
-
gb =
|
269
|
+
gb = 1073741824 #1gb in bytes
|
300
270
|
size = args[:VBDs][:physical_size].to_i * gb
|
301
271
|
vdi = client.vdis.create :name => "#{args[:name]}-disk1",
|
302
272
|
:storage_repository => storage_repository,
|
@@ -334,26 +304,19 @@ module ForemanXen
|
|
334
304
|
vm
|
335
305
|
end
|
336
306
|
|
337
|
-
def console
|
307
|
+
def console uuid
|
338
308
|
vm = find_vm_by_uuid(uuid)
|
339
|
-
|
309
|
+
raise 'VM is not running!' unless vm.ready?
|
340
310
|
|
341
311
|
console = vm.service.consoles.find { |c| c.__vm == vm.reference && c.protocol == 'rfb' }
|
342
|
-
|
312
|
+
raise "No console fore vm #{vm.name}" if console == nil
|
343
313
|
|
344
314
|
session_ref = (vm.service.instance_variable_get :@connection).instance_variable_get :@credentials
|
345
|
-
|
346
|
-
tunnel = VNCTunnel.new
|
315
|
+
fullURL = "#{console.location}&session_id=#{session_ref}"
|
316
|
+
tunnel = VNCTunnel.new fullURL
|
347
317
|
tunnel.start
|
348
318
|
logger.info 'VNCTunnel started'
|
349
|
-
WsProxy.start(
|
350
|
-
:host => tunnel.host,
|
351
|
-
:host_port => tunnel.port,
|
352
|
-
:password => ''
|
353
|
-
).merge(
|
354
|
-
:type => 'vnc',
|
355
|
-
:name => vm.name
|
356
|
-
)
|
319
|
+
WsProxy.start(:host => tunnel.host, :host_port => tunnel.port, :password => '').merge(:type => 'vnc', :name => vm.name)
|
357
320
|
|
358
321
|
rescue Error => e
|
359
322
|
logger.warn e
|
@@ -367,12 +330,7 @@ module ForemanXen
|
|
367
330
|
protected
|
368
331
|
|
369
332
|
def client
|
370
|
-
@client ||= ::Fog::Compute.new(
|
371
|
-
:provider => 'XenServer',
|
372
|
-
:xenserver_url => url,
|
373
|
-
:xenserver_username => user,
|
374
|
-
:xenserver_password => password
|
375
|
-
)
|
333
|
+
@client ||= ::Fog::Compute.new({ :provider => 'XenServer', :xenserver_url => url, :xenserver_username => user, :xenserver_password => password, :xenserver_redirect_to_master => true })
|
376
334
|
end
|
377
335
|
|
378
336
|
def disconnect
|
@@ -384,6 +342,7 @@ module ForemanXen
|
|
384
342
|
super.merge({})
|
385
343
|
end
|
386
344
|
|
345
|
+
|
387
346
|
private
|
388
347
|
|
389
348
|
def create_network(vm, args)
|
@@ -403,7 +362,7 @@ module ForemanXen
|
|
403
362
|
vm.reload
|
404
363
|
end
|
405
364
|
|
406
|
-
def xenstore_hash_flatten(nested_hash, key
|
365
|
+
def xenstore_hash_flatten(nested_hash, key=nil, keychain=nil, out_hash={})
|
407
366
|
nested_hash.each do |k, v|
|
408
367
|
if v.is_a? Hash
|
409
368
|
xenstore_hash_flatten(v, k, "#{keychain}#{k}/", out_hash)
|
@@ -412,6 +371,7 @@ module ForemanXen
|
|
412
371
|
end
|
413
372
|
end
|
414
373
|
out_hash
|
374
|
+
# @key = key
|
415
375
|
end
|
416
376
|
end
|
417
377
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
<%= text_f f, :user %>
|
3
3
|
<%= password_f f, :password %>
|
4
4
|
|
5
|
-
<% hypervisor = f.object.hypervisor.uuid rescue nil
|
5
|
+
<% hypervisor = f.object.hypervisor.uuid rescue nil%>
|
6
6
|
<% if hypervisor -%>
|
7
|
-
|
7
|
+
<%= f.hidden_field :uuid, :value => hypervisor %>
|
8
8
|
<% end -%>
|
9
9
|
<%= link_to_function _("Test Connection"), "testConnection(this)", :class => "btn + #{hypervisor.nil? ? "btn-default" : "btn-success"}", :'data-url' => test_connection_compute_resources_path %>
|
10
10
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div id='templates' class=''>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
</div>
|
2
|
+
<div class="form-group">
|
3
|
+
<%= selectable_f f, :hypervisor_host, [[_("Automatic allocation"), ""]] + compute_resource.avalable_hypervisors.map { |t| [t.name + " - " + (t.metrics.memory_free.to_f / t.metrics.memory_total.to_f * 100).round(2).to_s + "% free mem", t.name] }, {}, :class => 'form-control span2', :disabled => (controller_name != 'hosts'), :label => 'Hypervisor' %>
|
4
|
+
</div>
|
5
|
+
</div>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<div class="fields">
|
2
2
|
<div id='templates' class=''>
|
3
3
|
<div class="form-group">
|
4
|
-
<%= selectable_f f, :custom_template_name,
|
4
|
+
<%= selectable_f f, :custom_template_name,[[_("No template"), ""]] + compute_resource.custom_templates.map { |t| [t.name, t.name] }, { :selected => attribute_map[:template_selected_custom] }, :class => 'form-control span2', :label => 'Custom Template' %>
|
5
5
|
</div>
|
6
6
|
|
7
7
|
<div class="form-group ">
|
8
|
-
<%= selectable_f f, :builtin_template_name,
|
8
|
+
<%= selectable_f f, :builtin_template_name,[[_("No template"), ""]] + compute_resource.builtin_templates.map { |t| [t.name, t.name] }, { :selected => attribute_map[:template_selected_builtin] }, :class => 'form-control span2', :label => 'Builtin Template' %>
|
9
9
|
</div>
|
10
10
|
</div>
|
11
11
|
</div>
|