vagrant-xenserver-jc 0.0.13
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 +7 -0
- data/.gitignore +9 -0
- data/CHANGELOG.md +40 -0
- data/Gemfile +14 -0
- data/LICENSE +8 -0
- data/README.md +167 -0
- data/Rakefile +14 -0
- data/example_box/install_wheezy.sh +128 -0
- data/example_box/metadata.json +3 -0
- data/example_box/mkbox.sh +17 -0
- data/lib/vagrant-xenserver/action/clone_disk.rb +30 -0
- data/lib/vagrant-xenserver/action/clone_vm.rb +30 -0
- data/lib/vagrant-xenserver/action/configure_network.rb +61 -0
- data/lib/vagrant-xenserver/action/connect_xs.rb +47 -0
- data/lib/vagrant-xenserver/action/create_template.rb +87 -0
- data/lib/vagrant-xenserver/action/create_vifs.rb +86 -0
- data/lib/vagrant-xenserver/action/create_vm.rb +95 -0
- data/lib/vagrant-xenserver/action/destroy_vm.rb +37 -0
- data/lib/vagrant-xenserver/action/download_xva.rb +101 -0
- data/lib/vagrant-xenserver/action/dummy.rb +16 -0
- data/lib/vagrant-xenserver/action/halt_vm.rb +23 -0
- data/lib/vagrant-xenserver/action/is_created.rb +20 -0
- data/lib/vagrant-xenserver/action/is_running.rb +20 -0
- data/lib/vagrant-xenserver/action/is_suspended.rb +20 -0
- data/lib/vagrant-xenserver/action/prepare_nfs_settings.rb +85 -0
- data/lib/vagrant-xenserver/action/prepare_nfs_valid_ids.rb +17 -0
- data/lib/vagrant-xenserver/action/read_ssh_info.rb +97 -0
- data/lib/vagrant-xenserver/action/read_state.rb +35 -0
- data/lib/vagrant-xenserver/action/resume_vm.rb +30 -0
- data/lib/vagrant-xenserver/action/set_vm_params.rb +28 -0
- data/lib/vagrant-xenserver/action/start_vm.rb +31 -0
- data/lib/vagrant-xenserver/action/suspend_vm.rb +30 -0
- data/lib/vagrant-xenserver/action/upload_vhd.rb +164 -0
- data/lib/vagrant-xenserver/action/upload_xva.rb +100 -0
- data/lib/vagrant-xenserver/action/validate_network.rb +112 -0
- data/lib/vagrant-xenserver/action/wait_himn.rb +58 -0
- data/lib/vagrant-xenserver/action.rb +272 -0
- data/lib/vagrant-xenserver/config.rb +102 -0
- data/lib/vagrant-xenserver/errors.rb +68 -0
- data/lib/vagrant-xenserver/plugin.rb +70 -0
- data/lib/vagrant-xenserver/provider.rb +36 -0
- data/lib/vagrant-xenserver/util/exnhandler.rb +49 -0
- data/lib/vagrant-xenserver/util/uploader.rb +215 -0
- data/lib/vagrant-xenserver/version.rb +6 -0
- data/lib/vagrant-xenserver.rb +17 -0
- data/locales/en.yml +38 -0
- data/vagrant-xenserver.gemspec +27 -0
- metadata +173 -0
@@ -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
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "xmlrpc/client"
|
3
|
+
require "vagrant-xenserver/util/uploader"
|
4
|
+
require "rexml/document"
|
5
|
+
require "json"
|
6
|
+
require "xenapi"
|
7
|
+
|
8
|
+
module VagrantPlugins
|
9
|
+
module XenServer
|
10
|
+
module Action
|
11
|
+
class StartVM
|
12
|
+
def initialize(app, env)
|
13
|
+
@app = app
|
14
|
+
@logger = Log4r::Logger.new("vagrant::xenserver::actions::start_vm")
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
myvm = env[:machine].id
|
19
|
+
|
20
|
+
begin
|
21
|
+
env[:xc].VM.start(myvm,false,false)
|
22
|
+
rescue XenApi::Errors::NoHostsAvailable
|
23
|
+
raise Errors::NoHostsAvailable
|
24
|
+
end
|
25
|
+
|
26
|
+
@app.call env
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "xmlrpc/client"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module XenServer
|
6
|
+
module Action
|
7
|
+
class SuspendVM
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant::xenserver::actions::suspend_vm")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
myvm = env[:machine].id
|
15
|
+
|
16
|
+
suspend_task = env[:xc].Async.VM.suspend(myvm)
|
17
|
+
while env[:xc].task.get_status(suspend_task) == 'pending' do
|
18
|
+
sleep 1
|
19
|
+
end
|
20
|
+
suspend_result = env[:xc].task.get_status(suspend_task)
|
21
|
+
if suspend_result != "success"
|
22
|
+
raise Errors::APIError
|
23
|
+
end
|
24
|
+
|
25
|
+
@app.call env
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "xenapi"
|
3
|
+
require "vagrant-xenserver/util/uploader"
|
4
|
+
require "vagrant-xenserver/util/exnhandler"
|
5
|
+
require "rexml/document"
|
6
|
+
require "json"
|
7
|
+
|
8
|
+
module VagrantPlugins
|
9
|
+
module XenServer
|
10
|
+
module Action
|
11
|
+
class UploadVHD
|
12
|
+
|
13
|
+
@@lock = Mutex.new
|
14
|
+
|
15
|
+
def initialize(app, env)
|
16
|
+
@app = app
|
17
|
+
@logger = Log4r::Logger.new("vagrant::xenserver::actions::upload_vhd")
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_vhd_size(box_vhd_file)
|
21
|
+
# Find out virtual size of the VHD
|
22
|
+
disk_info={}
|
23
|
+
begin
|
24
|
+
begin
|
25
|
+
disk_info=JSON.parse(IO.popen(["qemu-img", "info",box_vhd_file,"--output=json"]).read)
|
26
|
+
rescue JSON::ParserError
|
27
|
+
size=`qemu-img info #{box_vhd_file} | grep "virtual size" | cut "-d(" -f2 | cut "-d " -f1`
|
28
|
+
disk_info['virtual-size']=size.strip
|
29
|
+
end
|
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
|
36
|
+
|
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
|
40
|
+
|
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
|
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
|
157
|
+
end
|
158
|
+
|
159
|
+
@app.call(env)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "xmlrpc/client"
|
3
|
+
require "vagrant-xenserver/util/uploader"
|
4
|
+
require "rexml/document"
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module XenServer
|
8
|
+
module Action
|
9
|
+
class UploadXVA
|
10
|
+
def initialize(app, env)
|
11
|
+
@app = app
|
12
|
+
@logger = Log4r::Logger.new("vagrant::xenserver::actions::upload_xva")
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
box_name = env[:machine].box.name.to_s
|
17
|
+
box_version = env[:machine].box.version.to_s
|
18
|
+
|
19
|
+
Action.getlock.synchronize do
|
20
|
+
templates = env[:xc].VM.get_all_records_where("field \"is_a_template\"=\"true\"")
|
21
|
+
template = templates.detect { |vm,vmr|
|
22
|
+
vmr["other_config"]["box_name"] == box_name &&
|
23
|
+
vmr["other_config"]["box_version"] == box_version
|
24
|
+
}
|
25
|
+
|
26
|
+
box_xva_file = env[:machine].box.directory.join('box.xva').to_s
|
27
|
+
|
28
|
+
if File.exist?(box_xva_file) && template.nil?
|
29
|
+
#box_image_file = env[:machine].box.directory.join('export.xva').to_s
|
30
|
+
hostname = env[:machine].provider_config.xs_host
|
31
|
+
session = env[:session]
|
32
|
+
|
33
|
+
@logger.info("box name=" + env[:machine].box.name.to_s)
|
34
|
+
@logger.info("box version=" + env[:machine].box.version.to_s)
|
35
|
+
|
36
|
+
# Create a task to so we can get the result of the upload
|
37
|
+
task = env[:xc].task.create("vagrant-xva-upload",
|
38
|
+
"Task to track progress of the XVA upload from vagrant")
|
39
|
+
|
40
|
+
url = "https://#{hostname}/import?session_id=#{env[:xc].xenapi_session}&task_id=#{task}"
|
41
|
+
|
42
|
+
uploader_options = {}
|
43
|
+
uploader_options[:ui] = env[:ui]
|
44
|
+
uploader_options[:insecure] = true
|
45
|
+
|
46
|
+
uploader = MyUtil::Uploader.new(box_xva_file, url, uploader_options)
|
47
|
+
|
48
|
+
begin
|
49
|
+
uploader.upload!
|
50
|
+
rescue
|
51
|
+
env[:xc].task.cancel(task)
|
52
|
+
end
|
53
|
+
|
54
|
+
task_status = ""
|
55
|
+
|
56
|
+
begin
|
57
|
+
sleep(0.2)
|
58
|
+
task_status = env[:xc].task.get_status(task)
|
59
|
+
end while task_status == "pending"
|
60
|
+
|
61
|
+
if task_status != "success"
|
62
|
+
# Task failed - let's find out why:
|
63
|
+
error_list = env[:xc].task.get_error_info(task)
|
64
|
+
MyUtil::Exnhandler.handle("VM.import", error_list)
|
65
|
+
end
|
66
|
+
|
67
|
+
task_result = env[:xc].task.get_result(task)
|
68
|
+
|
69
|
+
doc = REXML::Document.new(task_result)
|
70
|
+
|
71
|
+
@logger.debug("task_result=\"#{task_result}\"")
|
72
|
+
template_ref = doc.elements['value/array/data/value'].text
|
73
|
+
|
74
|
+
@logger.info("template_ref=" + template_ref)
|
75
|
+
|
76
|
+
# Make sure it's really a template, and add the xva_url to other_config:
|
77
|
+
env[:xc].VM.set_is_a_template(template_ref,true)
|
78
|
+
env[:xc].VM.add_to_other_config(template_ref,"box_name",box_name)
|
79
|
+
env[:xc].VM.add_to_other_config(template_ref,"box_version",box_version)
|
80
|
+
|
81
|
+
# Hackity hack: HVM booting guests don't need to set the bootable flag
|
82
|
+
# on their VBDs, but PV do. Let's set bootable=true on VBD device=0
|
83
|
+
# just in case.
|
84
|
+
|
85
|
+
vbds = env[:xc].VM.get_VBDs(template_ref)
|
86
|
+
vbds.each { |vbd|
|
87
|
+
if env[:xc].VBD.get_userdevice(vbd) == "0"
|
88
|
+
env[:xc].VBD.set_bootable(vbd, true)
|
89
|
+
end
|
90
|
+
}
|
91
|
+
env[:template] = template_ref
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
@app.call(env)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "xmlrpc/client"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module XenServer
|
6
|
+
module Action
|
7
|
+
class ValidateNetwork
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant::xenserver::actions::validate_network")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
myvm = env[:machine].id
|
15
|
+
|
16
|
+
# only find network without :fowarded port, then sort by name label
|
17
|
+
vifs = env[:machine].config.vm.networks.reject {
|
18
|
+
|k,v| k == :forwarded_port}.sort_by {
|
19
|
+
|k,v| v[:network] || ""}
|
20
|
+
|
21
|
+
# this will hold any vifs with no device (ethX)
|
22
|
+
vifs_unknown = []
|
23
|
+
|
24
|
+
# create a placeholder hash for all vifs
|
25
|
+
# note that eth0 is already used by HIMN, so start with 1
|
26
|
+
eth = Hash.new
|
27
|
+
vifs.count.times do |x|
|
28
|
+
x += 1
|
29
|
+
eth["eth#{x}".to_sym] = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get All networks without HIMN
|
33
|
+
allnetworks = env[:xc].network.get_all_records.reject {
|
34
|
+
|ref,net| net['other_config']['is_host_internal_management_network'] }
|
35
|
+
|
36
|
+
# find the network type (public/external or private/single-server)
|
37
|
+
allnets = {}
|
38
|
+
allnetworks.each do |ref, params|
|
39
|
+
allnets[ref] = params
|
40
|
+
allnets[ref]["network_type"] = params["PIFs"].empty? ? "private_network" : "external_network"
|
41
|
+
end
|
42
|
+
# convert allnets to string for error message
|
43
|
+
allnets_str = allnets.map { |k,v| "#{v['name_label']} (#{v['network_type']})"}.join(", ")
|
44
|
+
|
45
|
+
# foreach vifs which has device defined, assign it to `eth` Hash
|
46
|
+
vifs.each do |k,v|
|
47
|
+
# Check if network name label in configuration matches
|
48
|
+
# the network on Xenserver Host
|
49
|
+
netrefrec = allnets.find { |ref,net| net['name_label'].upcase == v[:network].upcase }
|
50
|
+
(net_ref, net_rec) = netrefrec
|
51
|
+
if net_ref.nil?
|
52
|
+
raise Errors::InvalidNetwork, network: v[:network], allnetwork: allnets_str, vm: env[:machine].name
|
53
|
+
end
|
54
|
+
|
55
|
+
# Assign network UUID/ref
|
56
|
+
v[:net_ref] = net_ref
|
57
|
+
|
58
|
+
# Assign network type
|
59
|
+
v[:network_type] = net_rec["network_type"]
|
60
|
+
|
61
|
+
# no match, assign a device number (ethX) later
|
62
|
+
if v[:device].nil?
|
63
|
+
# vifs_unknown will contains vifs without :device defined
|
64
|
+
# SORTED BY NETWORK NAME LABEL
|
65
|
+
vifs_unknown.push(v)
|
66
|
+
else
|
67
|
+
if v[:device].start_with?("eth") and eth.include?(v[:device].to_sym)
|
68
|
+
eth[v[:device].to_sym] = v
|
69
|
+
else
|
70
|
+
raise "Configration Error in netowrk `#{v[:network]}' for device name `#{v[:device]}'"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Populate `eth' hash from the rest of unconfigured vifs
|
76
|
+
vifs_unknown.each do |vif|
|
77
|
+
unconfigured_eth = eth.find {|k,v| v.empty?}[0]
|
78
|
+
vif[:device] = unconfigured_eth.to_s
|
79
|
+
eth[unconfigured_eth.to_sym] = vif
|
80
|
+
end
|
81
|
+
|
82
|
+
# Validate network settings:
|
83
|
+
# - if `ip' and dhcp is set, raise error
|
84
|
+
# - ip and netmask must be defined it dhcp is not set
|
85
|
+
# - external_network
|
86
|
+
# - can have gateway
|
87
|
+
# - private_network (internal xenserver host-only network)
|
88
|
+
# - CANNOT have gateway
|
89
|
+
# - if `ip' defined, raise error if dhcp is set
|
90
|
+
eth.each do |e, opt|
|
91
|
+
raise Errors::InvalidInterface, eth: e, opt: opt[:proto], net: opt[:network],
|
92
|
+
message: "No IP address is defined" if opt[:proto] == 'static' and opt[:ip].nil?
|
93
|
+
|
94
|
+
raise Errors::InvalidInterface, eth: e, opt: opt[:proto], net: opt[:network],
|
95
|
+
message: "No IP netmask is defined" if opt[:proto] == 'static' and opt[:netmask].nil?
|
96
|
+
|
97
|
+
raise Errors::InvalidInterface, eth: e, opt: opt[:proto], net: opt[:network],
|
98
|
+
message: "Cannot assign IP #{opt[:ip]} here" if opt[:proto] == 'dhcp' and !opt[:ip].nil?
|
99
|
+
|
100
|
+
raise Errors::InvalidInterface, eth: e, opt: opt[:network_type], net: opt[:network],
|
101
|
+
message: "Cannot assign gateway #{opt[:gateway]} here" if opt[:network_type] == "private_network" and !opt[:gateway].nil?
|
102
|
+
end
|
103
|
+
|
104
|
+
# Put eth on global env
|
105
|
+
env[:vifs] = eth
|
106
|
+
|
107
|
+
@app.call env
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module XenServer
|
5
|
+
module Action
|
6
|
+
# This action wait for SSH Communicator via HIMN interface is ready
|
7
|
+
class WaitForHIMNCommunicator
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_xenserver::action::wait_himn")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
if env[:machine].provider_config.use_himn
|
15
|
+
env[:machine_ssh_info] = wait_ssh_via_himn(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
@app.call(env)
|
19
|
+
end
|
20
|
+
|
21
|
+
def wait_ssh_via_himn(env)
|
22
|
+
machine = env[:machine]
|
23
|
+
return nil if machine.id.nil?
|
24
|
+
|
25
|
+
# Find the machine
|
26
|
+
networks = env[:xc].network.get_all_records
|
27
|
+
|
28
|
+
begin
|
29
|
+
vifs = env[:xc].VM.get_VIFs(machine.id)
|
30
|
+
rescue
|
31
|
+
@logger.info("Machine couldn't be found, assuming it got destroyed.")
|
32
|
+
machine.id = nil
|
33
|
+
return nil
|
34
|
+
end
|
35
|
+
|
36
|
+
himn = networks.find { |ref,net| net['other_config']['is_host_internal_management_network'] }
|
37
|
+
(himn_ref,himn_rec) = himn
|
38
|
+
|
39
|
+
assigned_ips = himn_rec['assigned_ips']
|
40
|
+
(vif,ip) = assigned_ips.find { |vif,ip| vifs.include? vif }
|
41
|
+
command = "ssh '#{machine.provider_config.xs_host}' -l '#{machine.provider_config.xs_username}' \"true &>/dev/null </dev/tcp/#{ip.to_s}/22 && echo open || echo closed\""
|
42
|
+
max_retry = 20
|
43
|
+
begin
|
44
|
+
retries ||= 0
|
45
|
+
ssh_ready = `#{command}`.strip
|
46
|
+
sleep 1
|
47
|
+
raise if ssh_ready == "closed"
|
48
|
+
rescue
|
49
|
+
if retries == max_retry
|
50
|
+
raise Errors::HIMNCommunicatorError
|
51
|
+
end
|
52
|
+
retry if (retries += 1) <= max_retry
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|