vagrant-xenserver 0.0.11 → 0.0.12
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.
- checksums.yaml +4 -4
- data/README.md +103 -25
- data/example_box/install_wheezy.sh +128 -0
- data/example_box/mkbox.sh +17 -0
- data/lib/vagrant-xenserver/action.rb +14 -4
- data/lib/vagrant-xenserver/action/clone_disk.rb +1 -1
- data/lib/vagrant-xenserver/action/clone_vm.rb +35 -0
- data/lib/vagrant-xenserver/action/connect_xs.rb +19 -11
- data/lib/vagrant-xenserver/action/create_template.rb +86 -0
- data/lib/vagrant-xenserver/action/create_vifs.rb +44 -23
- data/lib/vagrant-xenserver/action/create_vm.rb +14 -10
- data/lib/vagrant-xenserver/action/destroy_vm.rb +9 -6
- data/lib/vagrant-xenserver/action/download_xva.rb +96 -0
- data/lib/vagrant-xenserver/action/halt_vm.rb +1 -5
- data/lib/vagrant-xenserver/action/prepare_nfs_valid_ids.rb +1 -1
- data/lib/vagrant-xenserver/action/read_ssh_info.rb +48 -12
- data/lib/vagrant-xenserver/action/read_state.rb +4 -5
- data/lib/vagrant-xenserver/action/resume_vm.rb +3 -3
- data/lib/vagrant-xenserver/action/set_vm_params.rb +28 -0
- data/lib/vagrant-xenserver/action/start_vm.rb +7 -2
- data/lib/vagrant-xenserver/action/suspend_vm.rb +3 -3
- data/lib/vagrant-xenserver/action/upload_vhd.rb +130 -115
- data/lib/vagrant-xenserver/action/upload_xva.rb +63 -50
- data/lib/vagrant-xenserver/config.rb +45 -0
- data/lib/vagrant-xenserver/errors.rb +20 -0
- data/lib/vagrant-xenserver/plugin.rb +8 -0
- data/lib/vagrant-xenserver/util/exnhandler.rb +49 -0
- data/lib/vagrant-xenserver/version.rb +1 -1
- data/locales/en.yml +20 -1
- data/vagrant-xenserver.gemspec +1 -0
- metadata +24 -5
- data/lib/vagrant-xenserver/action/maybe_upload_disk.rb +0 -85
- data/test +0 -0
@@ -19,15 +19,14 @@ module VagrantPlugins
|
|
19
19
|
def read_state(xc, session, machine)
|
20
20
|
return :not_created if machine.id.nil?
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
begin
|
23
|
+
result = xc.VM.get_record(machine.id)
|
24
|
+
return result['power_state']
|
25
|
+
rescue
|
25
26
|
@logger.info("Machine not found. Assuming it has been destroyed.")
|
26
27
|
machine.id = nil
|
27
28
|
return :not_created
|
28
29
|
end
|
29
|
-
|
30
|
-
return result["Value"]['power_state']
|
31
30
|
end
|
32
31
|
end
|
33
32
|
end
|
@@ -13,11 +13,11 @@ module VagrantPlugins
|
|
13
13
|
def call(env)
|
14
14
|
myvm = env[:machine].id
|
15
15
|
|
16
|
-
resume_task = env[:xc].
|
17
|
-
while env[:xc].
|
16
|
+
resume_task = env[:xc].Async.VM.resume(myvm,false,false)
|
17
|
+
while env[:xc].task.get_status(resume_task) == 'pending' do
|
18
18
|
sleep 1
|
19
19
|
end
|
20
|
-
resume_result = env[:xc].
|
20
|
+
resume_result = env[:xc].task.get_status(resume_task)
|
21
21
|
if resume_result != "success"
|
22
22
|
raise Errors::APIError
|
23
23
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module XenServer
|
5
|
+
module Action
|
6
|
+
class SetVMParams
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new("vagrant::xenserver::actions::set_vm_params")
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
myvm = env[:machine].id
|
14
|
+
|
15
|
+
if env[:machine].provider_config.pv
|
16
|
+
env[:xc].VM.set_HVM_boot_policy(myvm,"")
|
17
|
+
env[:xc].VM.set_PV_bootloader(myvm,"pygrub")
|
18
|
+
end
|
19
|
+
|
20
|
+
mem = ((env[:machine].provider_config.memory) * (1024*1024)).to_s
|
21
|
+
env[:xc].VM.set_memory_limits(myvm,mem,mem,mem,mem)
|
22
|
+
|
23
|
+
@app.call env
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -3,6 +3,7 @@ require "xmlrpc/client"
|
|
3
3
|
require "vagrant-xenserver/util/uploader"
|
4
4
|
require "rexml/document"
|
5
5
|
require "json"
|
6
|
+
require "xenapi"
|
6
7
|
|
7
8
|
module VagrantPlugins
|
8
9
|
module XenServer
|
@@ -15,8 +16,12 @@ module VagrantPlugins
|
|
15
16
|
|
16
17
|
def call(env)
|
17
18
|
myvm = env[:machine].id
|
18
|
-
|
19
|
-
|
19
|
+
|
20
|
+
begin
|
21
|
+
env[:xc].VM.start(myvm,false,false)
|
22
|
+
rescue XenApi::Errors::NoHostsAvailable
|
23
|
+
raise Errors::NoHostsAvailable
|
24
|
+
end
|
20
25
|
|
21
26
|
@app.call env
|
22
27
|
end
|
@@ -13,11 +13,11 @@ module VagrantPlugins
|
|
13
13
|
def call(env)
|
14
14
|
myvm = env[:machine].id
|
15
15
|
|
16
|
-
suspend_task = env[:xc].
|
17
|
-
while env[:xc].
|
16
|
+
suspend_task = env[:xc].Async.VM.suspend(myvm)
|
17
|
+
while env[:xc].task.get_status(suspend_task) == 'pending' do
|
18
18
|
sleep 1
|
19
19
|
end
|
20
|
-
suspend_result = env[:xc].
|
20
|
+
suspend_result = env[:xc].task.get_status(suspend_task)
|
21
21
|
if suspend_result != "success"
|
22
22
|
raise Errors::APIError
|
23
23
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "log4r"
|
2
|
-
require "
|
2
|
+
require "xenapi"
|
3
3
|
require "vagrant-xenserver/util/uploader"
|
4
|
+
require "vagrant-xenserver/util/exnhandler"
|
4
5
|
require "rexml/document"
|
5
6
|
require "json"
|
6
7
|
|
@@ -15,130 +16,144 @@ module VagrantPlugins
|
|
15
16
|
@app = app
|
16
17
|
@logger = Log4r::Logger.new("vagrant::xenserver::actions::upload_vhd")
|
17
18
|
end
|
18
|
-
|
19
|
-
def call(env)
|
20
|
-
box_vhd_file = env[:machine].box.directory.join('box.vhd').to_s
|
21
|
-
|
22
|
-
hostname = env[:machine].provider_config.xs_host
|
23
|
-
session = env[:session]
|
24
|
-
|
25
|
-
@logger.info("box name=" + env[:machine].box.name.to_s)
|
26
|
-
@logger.info("box version=" + env[:machine].box.version.to_s)
|
27
|
-
|
28
|
-
# Find out if it has already been uploaded
|
29
|
-
vdis = env[:xc].call("VDI.get_all_records", env[:session])['Value']
|
30
|
-
md5=`dd if=#{box_vhd_file} bs=1M count=1 | md5sum | cut '-d ' -f1`.strip
|
31
|
-
|
32
|
-
@logger.info("md5=#{md5}")
|
33
|
-
|
34
|
-
vdi_tag = "vagrant:" + env[:machine].box.name.to_s + "/" + md5
|
35
19
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
if not vdi_ref_rec
|
42
|
-
@@lock.synchronize do
|
43
|
-
# Find out virtual size of the VHD
|
44
|
-
disk_info={}
|
20
|
+
def get_vhd_size(box_vhd_file)
|
21
|
+
# Find out virtual size of the VHD
|
22
|
+
disk_info={}
|
23
|
+
begin
|
45
24
|
begin
|
46
25
|
disk_info=JSON.parse(IO.popen(["qemu-img", "info",box_vhd_file,"--output=json"]).read)
|
47
26
|
rescue JSON::ParserError
|
48
27
|
size=`qemu-img info #{box_vhd_file} | grep "virtual size" | cut "-d(" -f2 | cut "-d " -f1`
|
49
28
|
disk_info['virtual-size']=size.strip
|
50
29
|
end
|
51
|
-
|
52
|
-
@logger.
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
'name_label' => 'Vagrant disk',
|
58
|
-
'name_description' => 'Base disk uploaded for the vagrant box '+env[:machine].box.name.to_s+' v'+env[:machine].box.version.to_s,
|
59
|
-
'SR' => default_sr,
|
60
|
-
'virtual_size' => "#{virtual_size}",
|
61
|
-
'type' => 'user',
|
62
|
-
'sharable' => false,
|
63
|
-
'read_only' => false,
|
64
|
-
'other_config' => {},
|
65
|
-
'xenstore_data' => {},
|
66
|
-
'sm_config' => {},
|
67
|
-
'tags' => [] }
|
68
|
-
|
69
|
-
vdi_result=env[:xc].call("VDI.create",env[:session],vdi_record)['Value']
|
70
|
-
|
71
|
-
@logger.info("created VDI: " + vdi_result.to_s)
|
72
|
-
vdi_uuid = env[:xc].call("VDI.get_uuid",env[:session],vdi_result)['Value']
|
73
|
-
@logger.info("uuid: "+vdi_uuid)
|
74
|
-
|
75
|
-
# Create a task to so we can get the result of the upload
|
76
|
-
task_result = env[:xc].call("task.create", env[:session], "vagrant-vhd-upload",
|
77
|
-
"Task to track progress of the XVA upload from vagrant")
|
78
|
-
|
79
|
-
if task_result["Status"] != "Success"
|
80
|
-
raise Errors::APIError
|
81
|
-
end
|
82
|
-
|
83
|
-
task = task_result["Value"]
|
84
|
-
|
85
|
-
url = "https://#{hostname}/import_raw_vdi?session_id=#{session}&task_id=#{task}&vdi=#{vdi_result}&format=vhd"
|
86
|
-
|
87
|
-
uploader_options = {}
|
88
|
-
uploader_options[:ui] = env[:ui]
|
89
|
-
uploader_options[:insecure] = true
|
90
|
-
|
91
|
-
uploader = MyUtil::Uploader.new(box_vhd_file, url, uploader_options)
|
92
|
-
|
93
|
-
begin
|
94
|
-
uploader.upload!
|
95
|
-
rescue Errors::UploaderInterrupted
|
96
|
-
env[:ui].info(I18n.t("vagrant.xenserver.action.upload_xva.interrupted"))
|
97
|
-
raise
|
98
|
-
end
|
99
|
-
|
100
|
-
task_status = ""
|
101
|
-
|
102
|
-
begin
|
103
|
-
sleep(0.2)
|
104
|
-
task_status_result = env[:xc].call("task.get_status",env[:session],task)
|
105
|
-
if task_status_result["Status"] != "Success"
|
106
|
-
raise Errors::APIError
|
107
|
-
end
|
108
|
-
task_status = task_status_result["Value"]
|
109
|
-
end while task_status == "pending"
|
110
|
-
|
111
|
-
@logger.info("task_status="+task_status)
|
112
|
-
|
113
|
-
if task_status != "success"
|
114
|
-
raise Errors::APIError
|
115
|
-
end
|
116
|
-
|
117
|
-
task_result_result = env[:xc].call("task.get_result",env[:session],task)
|
118
|
-
if task_result_result["Status"] != "Success"
|
119
|
-
raise Errors::APIError
|
120
|
-
end
|
121
|
-
|
122
|
-
task_result = task_result_result["Value"]
|
123
|
-
|
124
|
-
doc = REXML::Document.new(task_result)
|
125
|
-
|
126
|
-
doc.elements.each('value/array/data/value') do |ele|
|
127
|
-
vdi = ele.text
|
128
|
-
end
|
129
|
-
|
130
|
-
@logger.info("task_result=" + task_result)
|
30
|
+
rescue
|
31
|
+
@logger.error("Error getting virtual size of VHD: #{box_vhd_file}")
|
32
|
+
raise Errors::QemuImgError
|
33
|
+
end
|
34
|
+
return disk_info['virtual-size']
|
35
|
+
end
|
131
36
|
|
132
|
-
|
133
|
-
|
37
|
+
def call(env)
|
38
|
+
if env[:machine].provider_config.xva_url.nil?
|
39
|
+
box_vhd_file = env[:machine].box.directory.join('box.vhd').to_s
|
134
40
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
41
|
+
if File.exist?(box_vhd_file)
|
42
|
+
hostname = env[:machine].provider_config.xs_host
|
43
|
+
session = env[:xc].xenapi_session
|
44
|
+
|
45
|
+
@logger.info("box name=" + env[:machine].box.name.to_s)
|
46
|
+
@logger.info("box version=" + env[:machine].box.version.to_s)
|
47
|
+
|
48
|
+
md5=`dd if=#{box_vhd_file} bs=1M count=1 | md5sum | cut '-d ' -f1`.strip
|
49
|
+
|
50
|
+
@logger.info("md5=#{md5}")
|
51
|
+
|
52
|
+
# Find out if it has already been uploaded
|
53
|
+
@@lock.synchronize do
|
54
|
+
|
55
|
+
vdis = env[:xc].VDI.get_all_records
|
56
|
+
|
57
|
+
vdi_tag = "vagrant:" + env[:machine].box.name.to_s + "/" + md5
|
141
58
|
|
59
|
+
vdi_ref_rec = vdis.find { |reference,record|
|
60
|
+
@logger.info(record['tags'].to_s)
|
61
|
+
record['tags'].include?(vdi_tag)
|
62
|
+
}
|
63
|
+
|
64
|
+
if not vdi_ref_rec
|
65
|
+
virtual_size = get_vhd_size(box_vhd_file)
|
66
|
+
@logger.info("virtual_size=#{virtual_size}")
|
67
|
+
pool=env[:xc].pool.get_all
|
68
|
+
default_sr=env[:xc].pool.get_default_SR(pool[0])
|
69
|
+
@logger.info("default_SR="+default_sr)
|
70
|
+
|
71
|
+
# Verify the default SR is valid:
|
72
|
+
begin
|
73
|
+
env[:xc].SR.get_uuid(default_sr)
|
74
|
+
rescue
|
75
|
+
raise Errors::NoDefaultSR
|
76
|
+
end
|
77
|
+
|
78
|
+
vdi_record = {
|
79
|
+
'name_label' => 'Vagrant disk',
|
80
|
+
'name_description' => 'Base disk uploaded for the vagrant box '+env[:machine].box.name.to_s+' v'+env[:machine].box.version.to_s,
|
81
|
+
'SR' => default_sr,
|
82
|
+
'virtual_size' => "#{virtual_size}",
|
83
|
+
'type' => 'user',
|
84
|
+
'sharable' => false,
|
85
|
+
'read_only' => false,
|
86
|
+
'other_config' => {},
|
87
|
+
'xenstore_data' => {},
|
88
|
+
'sm_config' => {},
|
89
|
+
'tags' => [] }
|
90
|
+
|
91
|
+
begin
|
92
|
+
vdi_result=env[:xc].VDI.create(vdi_record)
|
93
|
+
rescue XenApi::Errors::GenericError => e
|
94
|
+
MyUtil::Exnhandler.handle_xenapiexn("VDI.create",e,@logger)
|
95
|
+
end
|
96
|
+
|
97
|
+
@logger.info("created VDI: " + vdi_result.to_s)
|
98
|
+
vdi_uuid = env[:xc].VDI.get_uuid(vdi_result)
|
99
|
+
@logger.info("uuid: "+vdi_uuid)
|
100
|
+
|
101
|
+
# Create a task to so we can get the result of the upload
|
102
|
+
task = env[:xc].task.create("vagrant-vhd-upload",
|
103
|
+
"Task to track progress of the XVA upload from vagrant")
|
104
|
+
|
105
|
+
url = "https://#{hostname}/import_raw_vdi?session_id=#{session}&task_id=#{task}&vdi=#{vdi_result}&format=vhd"
|
106
|
+
|
107
|
+
uploader_options = {}
|
108
|
+
uploader_options[:ui] = env[:ui]
|
109
|
+
uploader_options[:insecure] = true
|
110
|
+
|
111
|
+
uploader = MyUtil::Uploader.new(box_vhd_file, url, uploader_options)
|
112
|
+
|
113
|
+
begin
|
114
|
+
uploader.upload!
|
115
|
+
rescue
|
116
|
+
env[:xc].task.cancel(task)
|
117
|
+
end
|
118
|
+
|
119
|
+
task_status = ""
|
120
|
+
|
121
|
+
begin
|
122
|
+
sleep(0.2)
|
123
|
+
task_status = env[:xc].task.get_status(task)
|
124
|
+
end while task_status == "pending"
|
125
|
+
|
126
|
+
@logger.info("task_status="+task_status)
|
127
|
+
|
128
|
+
if task_status != "success"
|
129
|
+
# Task failed - let's find out why:
|
130
|
+
error_list = env[:xc].task.get_error_info(task)
|
131
|
+
MyUtil::Exnhandler.handle("import HTTP handler", error_list)
|
132
|
+
end
|
133
|
+
|
134
|
+
task_result = env[:xc].task.get_result(task)
|
135
|
+
|
136
|
+
doc = REXML::Document.new(task_result)
|
137
|
+
|
138
|
+
doc.elements.each('value/array/data/value') do |ele|
|
139
|
+
vdi = ele.text
|
140
|
+
end
|
141
|
+
|
142
|
+
@logger.info("task_result=" + task_result)
|
143
|
+
|
144
|
+
tag_result=env[:xc].VDI.add_tags(vdi_result,vdi_tag)
|
145
|
+
|
146
|
+
@logger.info("Added tags")
|
147
|
+
|
148
|
+
env[:box_vdi] = vdi_result
|
149
|
+
else
|
150
|
+
(reference,record) = vdi_ref_rec
|
151
|
+
env[:box_vdi] = reference
|
152
|
+
@logger.info("box_vdi="+reference)
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
142
157
|
end
|
143
158
|
|
144
159
|
@app.call(env)
|
@@ -11,73 +11,86 @@ module VagrantPlugins
|
|
11
11
|
@app = app
|
12
12
|
@logger = Log4r::Logger.new("vagrant::xenserver::actions::upload_xva")
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def call(env)
|
16
|
-
|
17
|
-
|
18
|
-
hostname = env[:machine].provider_config.xs_host
|
19
|
-
session = env[:session]
|
20
|
-
|
21
|
-
@logger.info("box name=" + env[:machine].box.name.to_s)
|
22
|
-
@logger.info("box version=" + env[:machine].box.version.to_s)
|
23
|
-
|
24
|
-
# Create a task to so we can get the result of the upload
|
25
|
-
task_result = env[:xc].call("task.create", env[:session], "vagrant-xva-upload",
|
26
|
-
"Task to track progress of the XVA upload from vagrant")
|
27
|
-
|
28
|
-
if task_result["Status"] != "Success"
|
29
|
-
raise Errors::APIError
|
30
|
-
end
|
16
|
+
box_name = env[:machine].box.name.to_s
|
17
|
+
box_version = env[:machine].box.version.to_s
|
31
18
|
|
32
|
-
|
19
|
+
templates = env[:xc].VM.get_all_records_where("field \"is_a_template\"=\"true\"")
|
20
|
+
template = templates.detect { |vm,vmr|
|
21
|
+
vmr["other_config"]["box_name"] == box_name &&
|
22
|
+
vmr["other_config"]["box_version"] == box_version
|
23
|
+
}
|
33
24
|
|
34
|
-
|
25
|
+
box_xva_file = env[:machine].box.directory.join('box.xva').to_s
|
35
26
|
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
if File.exist?(box_xva_file) && template.nil?
|
28
|
+
#box_image_file = env[:machine].box.directory.join('export.xva').to_s
|
29
|
+
hostname = env[:machine].provider_config.xs_host
|
30
|
+
session = env[:session]
|
39
31
|
|
40
|
-
|
32
|
+
@logger.info("box name=" + env[:machine].box.name.to_s)
|
33
|
+
@logger.info("box version=" + env[:machine].box.version.to_s)
|
41
34
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
35
|
+
# Create a task to so we can get the result of the upload
|
36
|
+
task = env[:xc].task.create("vagrant-xva-upload",
|
37
|
+
"Task to track progress of the XVA upload from vagrant")
|
38
|
+
|
39
|
+
url = "https://#{hostname}/import?session_id=#{env[:xc].xenapi_session}&task_id=#{task}"
|
48
40
|
|
49
|
-
|
41
|
+
uploader_options = {}
|
42
|
+
uploader_options[:ui] = env[:ui]
|
43
|
+
uploader_options[:insecure] = true
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
45
|
+
uploader = MyUtil::Uploader.new(box_xva_file, url, uploader_options)
|
46
|
+
|
47
|
+
begin
|
48
|
+
uploader.upload!
|
49
|
+
rescue
|
50
|
+
env[:xc].task.cancel(task)
|
56
51
|
end
|
57
|
-
task_status = task_status_result["Value"]
|
58
|
-
end while task_status == "pending"
|
59
52
|
|
60
|
-
|
53
|
+
task_status = ""
|
61
54
|
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
begin
|
56
|
+
sleep(0.2)
|
57
|
+
task_status = env[:xc].task.get_status(task)
|
58
|
+
end while task_status == "pending"
|
65
59
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
60
|
+
if task_status != "success"
|
61
|
+
# Task failed - let's find out why:
|
62
|
+
error_list = env[:xc].task.get_error_info(task)
|
63
|
+
MyUtil::Exnhandler.handle("VM.import", error_list)
|
64
|
+
end
|
70
65
|
|
71
|
-
|
66
|
+
task_result = env[:xc].task.get_result(task)
|
72
67
|
|
73
|
-
|
68
|
+
doc = REXML::Document.new(task_result)
|
74
69
|
|
75
|
-
|
76
|
-
|
77
|
-
|
70
|
+
@logger.debug("task_result=\"#{task_result}\"")
|
71
|
+
template_ref = doc.elements['value/array/data/value'].text
|
72
|
+
|
73
|
+
@logger.info("template_ref=" + template_ref)
|
78
74
|
|
79
|
-
|
75
|
+
# Make sure it's really a template, and add the xva_url to other_config:
|
76
|
+
env[:xc].VM.set_is_a_template(template_ref,true)
|
77
|
+
env[:xc].VM.add_to_other_config(template_ref,"box_name",box_name)
|
78
|
+
env[:xc].VM.add_to_other_config(template_ref,"box_version",box_version)
|
79
|
+
|
80
|
+
# Hackity hack: HVM booting guests don't need to set the bootable flag
|
81
|
+
# on their VBDs, but PV do. Let's set bootable=true on VBD device=0
|
82
|
+
# just in case.
|
83
|
+
|
84
|
+
vbds = env[:xc].VM.get_VBDs(template_ref)
|
85
|
+
vbds.each { |vbd|
|
86
|
+
if env[:xc].VBD.get_userdevice(vbd) == "0"
|
87
|
+
env[:xc].VBD.set_bootable(vbd, true)
|
88
|
+
end
|
89
|
+
}
|
90
|
+
env[:template] = template_ref
|
91
|
+
end
|
80
92
|
|
93
|
+
@app.call(env)
|
81
94
|
end
|
82
95
|
end
|
83
96
|
end
|