vagrant-xenserver 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f0cec68cbb7af733bd030330a8220b43d73c06b4
4
- data.tar.gz: 6d87fb9aa7926950fbaa93df55d395bcfd190032
3
+ metadata.gz: 863a12a0d4f0def43d9e81dc02d35aa71d2c2992
4
+ data.tar.gz: 72bb9e377c24be9a249c3d23cbe827d9be1c47a4
5
5
  SHA512:
6
- metadata.gz: f993a2dd8ff4737cf27bc81f3e255af09e3f7f4723c2640ff741a254dc2df846c730e69a65a159b1705bbd1d0fdb9fb818e401f63c3da6e2a23751411258d7ae
7
- data.tar.gz: 2ec61fc6f4638f0a77e9051d7744c95e3e43147f5ee7db75c2b90dbda821dfcf0c32e9a1fea6f0749e4ace92f85747e4e185a3295aaeaa44699e15b06849b44d
6
+ metadata.gz: 24a88789435fd29b0f6a9c43bc31275bb4a260a444ccc1c9fd4e6f54c8d4f60d7ef99864aab262feebd229ca77dbf1b631875354c34cd7977869b74ebfe8eaf1
7
+ data.tar.gz: aa8d34e7b64708274df83a175c396fc49f44ac2e3e57daabb59e5b839225284362454e62b96074577bc4c92fc48d0408a6f218bbcb6cbde85209a14bc681919c
@@ -6,6 +6,11 @@ module VagrantPlugins
6
6
  module Action
7
7
  include Vagrant::Action::Builtin
8
8
  @logger = Log4r::Logger.new('vagrant::xenserver::action')
9
+ @xvalock = Mutex.new
10
+
11
+ def self.getlock
12
+ @xvalock
13
+ end
9
14
 
10
15
  def self.action_boot
11
16
  Vagrant::Action::Builder.new.tap do |b|
@@ -212,6 +217,21 @@ module VagrantPlugins
212
217
  end
213
218
  end
214
219
 
220
+ def self.action_reload
221
+ Vagrant::Action::Builder.new.tap do |b|
222
+ b.use Call, IsCreated do |env1, b2|
223
+ if !env1[:result]
224
+ b2.use MessageNotCreated
225
+ next
226
+ end
227
+
228
+ b2.use ConfigValidate
229
+ b2.use action_halt
230
+ b2.use action_boot
231
+ end
232
+ end
233
+ end
234
+
215
235
  action_root = Pathname.new(File.expand_path('../action', __FILE__))
216
236
  autoload :CreateVIFs, action_root.join("create_vifs")
217
237
  autoload :ConnectXS, action_root.join("connect_xs")
@@ -21,9 +21,12 @@ module VagrantPlugins
21
21
  else
22
22
  vm_name = env[:machine].provider_config.name
23
23
  end
24
-
25
- vm = env[:xc].VM.clone(template_ref, vm_name)
26
- env[:xc].VM.provision(vm)
24
+
25
+ vm = nil
26
+ Action.getlock.synchronize do
27
+ vm = env[:xc].VM.clone(template_ref, vm_name)
28
+ env[:xc].VM.provision(vm)
29
+ end
27
30
 
28
31
  env[:machine].id = vm
29
32
 
@@ -12,22 +12,28 @@ module VagrantPlugins
12
12
  end
13
13
 
14
14
  def call(env)
15
- if not env[:xc]
16
- config = env[:machine].provider_config
15
+ config = env[:machine].provider_config
16
+
17
+ # Only even try to connect if we've got a hostname
18
+ if (not env[:xc]) && (not config.xs_host.nil?)
17
19
  uri = URI::Generic.new(config.xs_use_ssl ? 'https' : 'http',
18
- nil,
19
- config.xs_host,
20
- config.xs_port,
21
- nil,
22
- "/",
23
- nil,
24
- nil, nil)
20
+ nil,
21
+ config.xs_host,
22
+ config.xs_port,
23
+ nil,
24
+ "/",
25
+ nil,
26
+ nil, nil)
25
27
  env[:xc] = XenApi::Client.new(uri.to_s, timeout = config.api_timeout)
26
28
 
27
29
  @logger.info("Connecting to XenServer")
28
30
 
29
- if not env[:xc].login_with_password(config.xs_username, config.xs_password)
31
+ begin
32
+ result = env[:xc].login_with_password(config.xs_username, config.xs_password)
33
+ rescue XenApi::Errors::SessionAuthenticationFailed
30
34
  raise Errors::LoginError
35
+ rescue
36
+ raise Errors::ConnectionError
31
37
  end
32
38
 
33
39
  @logger.info("Connected to XenServer")
@@ -39,4 +45,3 @@ module VagrantPlugins
39
45
  end
40
46
  end
41
47
  end
42
-
@@ -24,58 +24,59 @@ module VagrantPlugins
24
24
  # Let's create a VM and attach the uploaded VDI to it.
25
25
  # First see if we've done that already:
26
26
 
27
- templates = env[:xc].VM.get_all_records_where("field \"is_a_template\"=\"true\"")
28
- template = templates.detect { |vm,vmr|
29
- vmr["other_config"]["box_name"] == box_name &&
30
- vmr["other_config"]["box_version"] == box_version
31
- }
27
+ Action.getlock.synchronize do
28
+ templates = env[:xc].VM.get_all_records_where("field \"is_a_template\"=\"true\"")
29
+ template = templates.detect { |vm,vmr|
30
+ vmr["other_config"]["box_name"] == box_name &&
31
+ vmr["other_config"]["box_version"] == box_version
32
+ }
32
33
 
33
- if template.nil?
34
- vdi_ref = env[:box_vdi]
34
+ if template.nil?
35
+ vdi_ref = env[:box_vdi]
35
36
 
36
- oim = env[:xc].VM.get_by_name_label("Other install media")[0]
37
+ oim = env[:xc].VM.get_by_name_label("Other install media")[0]
37
38
 
38
- template_name = "#{box_name}.#{box_version}"
39
+ template_name = "#{box_name}.#{box_version}"
39
40
 
40
- template_ref = env[:xc].VM.clone(oim,template_name)
41
+ template_ref = env[:xc].VM.clone(oim,template_name)
41
42
 
42
- vbd_record = {
43
- 'VM' => template_ref,
44
- 'VDI' => env[:box_vdi],
45
- 'userdevice' => '0',
46
- 'bootable' => true,
47
- 'mode' => 'RW',
48
- 'type' => 'Disk',
49
- 'unpluggable' => false,
50
- 'empty' => false,
51
- 'other_config' => {},
52
- 'qos_algorithm_type' => '',
53
- 'qos_algorithm_params' => {}
54
- }
43
+ vbd_record = {
44
+ 'VM' => template_ref,
45
+ 'VDI' => env[:box_vdi],
46
+ 'userdevice' => '0',
47
+ 'bootable' => true,
48
+ 'mode' => 'RW',
49
+ 'type' => 'Disk',
50
+ 'unpluggable' => false,
51
+ 'empty' => false,
52
+ 'other_config' => {},
53
+ 'qos_algorithm_type' => '',
54
+ 'qos_algorithm_params' => {}
55
+ }
55
56
 
56
- vbd_res = env[:xc].VBD.create(vbd_record)
57
+ vbd_res = env[:xc].VBD.create(vbd_record)
57
58
 
58
- @logger.info("vbd_res=" + vbd_res.to_s)
59
+ @logger.info("vbd_res=" + vbd_res.to_s)
59
60
 
60
- env[:xc].VM.add_to_other_config(template_ref, "box_name", box_name)
61
- env[:xc].VM.add_to_other_config(template_ref, "box_version", box_version)
61
+ env[:xc].VM.add_to_other_config(template_ref, "box_name", box_name)
62
+ env[:xc].VM.add_to_other_config(template_ref, "box_version", box_version)
62
63
 
63
- if env[:machine].provider_config.pv
64
- env[:xc].VM.set_HVM_boot_policy(template_ref,"")
65
- env[:xc].VM.set_PV_bootloader(template_ref,"pygrub")
66
- end
64
+ if env[:machine].provider_config.pv
65
+ env[:xc].VM.set_HVM_boot_policy(template_ref,"")
66
+ env[:xc].VM.set_PV_bootloader(template_ref,"pygrub")
67
+ end
67
68
 
68
- mem = ((env[:machine].provider_config.memory) * (1024*1024)).to_s
69
- env[:xc].VM.set_memory_limits(template_ref,mem,mem,mem,mem)
69
+ mem = ((env[:machine].provider_config.memory) * (1024*1024)).to_s
70
+ env[:xc].VM.set_memory_limits(template_ref,mem,mem,mem,mem)
70
71
 
71
- env[:template] = template_ref
72
+ env[:template] = template_ref
72
73
 
73
- else
74
- @logger.info("Found pre-existing template for this box")
75
- (template_ref, template_rec) = template
76
- env[:template] = template_ref
74
+ else
75
+ @logger.info("Found pre-existing template for this box")
76
+ (template_ref, template_rec) = template
77
+ env[:template] = template_ref
78
+ end
77
79
  end
78
-
79
80
  end
80
81
 
81
82
  @app.call env
@@ -26,68 +26,73 @@ module VagrantPlugins
26
26
  # Check whether we've already downloaded a VM from this URL
27
27
  # When we do, we set an other_config key 'xva_url', so we
28
28
  # can just scan through the VMs looking for it.
29
- templates = env[:xc].VM.get_all_records_where("field \"is_a_template\"=\"true\"")
30
- template = templates.detect { |vm,vmr|
31
- vmr["other_config"]["box_name"] == box_name &&
32
- vmr["other_config"]["box_version"] == box_version
33
- }
34
-
35
- @logger.info("template="+template.to_s)
36
-
37
- if template.nil? && (not xva_url.nil?)
38
- # No template, let's download it.
39
- pool=env[:xc].pool.get_all
40
- default_sr=env[:xc].pool.get_default_SR(pool[0])
41
-
42
- env[:ui].output("Downloading XVA. This may take some time. Source URL: "+xva_url)
43
- task = env[:xc].Async.VM.import(xva_url, default_sr, false, false)
44
-
45
- begin
46
- sleep(2.0)
47
- task_status = env[:xc].task.get_status(task)
48
- task_progress = env[:xc].task.get_progress(task) * 100.0
49
- output = "Progress: #{task_progress.round(0)}%"
50
- env[:ui].clear_line
51
- env[:ui].detail(output, new_line: false)
52
- end while task_status == "pending"
53
29
 
54
- env[:ui].clear_line
30
+ template = nil
55
31
 
56
- if task_status != "success"
57
- # Task failed - let's find out why:
58
- error_list = env[:xc].task.get_error_info(task)
59
- MyUtil::Exnhandler.handle("Async.VM.import", error_list)
60
- end
32
+ Action.getlock.synchronize do
33
+ templates = env[:xc].VM.get_all_records_where("field \"is_a_template\"=\"true\"")
34
+ template = templates.detect { |vm,vmr|
35
+ vmr["other_config"]["box_name"] == box_name &&
36
+ vmr["other_config"]["box_version"] == box_version
37
+ }
38
+
39
+ @logger.info("template="+template.to_s)
61
40
 
62
- task_result = env[:xc].task.get_result(task)
41
+ if template.nil? && (not xva_url.nil?)
42
+ # No template, let's download it.
43
+ pool=env[:xc].pool.get_all
44
+ default_sr=env[:xc].pool.get_default_SR(pool[0])
63
45
 
64
- doc = REXML::Document.new(task_result)
46
+ env[:ui].output("Downloading XVA. This may take some time. Source URL: "+xva_url)
47
+ task = env[:xc].Async.VM.import(xva_url, default_sr, false, false)
65
48
 
66
- @logger.debug("task_result=\"#{task_result}\"")
67
- template_ref = doc.elements['value/array/data/value'].text
49
+ begin
50
+ sleep(2.0)
51
+ task_status = env[:xc].task.get_status(task)
52
+ task_progress = env[:xc].task.get_progress(task) * 100.0
53
+ output = "Progress: #{task_progress.round(0)}%"
54
+ env[:ui].clear_line
55
+ env[:ui].detail(output, new_line: false)
56
+ end while task_status == "pending"
57
+
58
+ env[:ui].clear_line
59
+
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("Async.VM.import", error_list)
64
+ end
68
65
 
69
- # Make sure it's really a template, and add the xva_url to other_config:
70
- env[:xc].VM.set_is_a_template(template_ref,true)
71
- env[:xc].VM.add_to_other_config(template_ref,"xva_url",xva_url)
72
- env[:xc].VM.add_to_other_config(template_ref,"box_name",box_name)
73
- env[:xc].VM.add_to_other_config(template_ref,"box_version",box_version)
66
+ task_result = env[:xc].task.get_result(task)
67
+
68
+ doc = REXML::Document.new(task_result)
69
+
70
+ @logger.debug("task_result=\"#{task_result}\"")
71
+ template_ref = doc.elements['value/array/data/value'].text
72
+
73
+ # Make sure it's really a template, and add the xva_url to other_config:
74
+ env[:xc].VM.set_is_a_template(template_ref,true)
75
+ env[:xc].VM.add_to_other_config(template_ref,"xva_url",xva_url)
76
+ env[:xc].VM.add_to_other_config(template_ref,"box_name",box_name)
77
+ env[:xc].VM.add_to_other_config(template_ref,"box_version",box_version)
74
78
 
75
79
  # Hackity hack: HVM booting guests don't need to set the bootable flag
76
80
  # on their VBDs, but PV do. Let's set bootable=true on VBD device=0
77
81
  # just in case.
78
82
 
79
- vbds = env[:xc].VM.get_VBDs(template_ref)
80
- vbds.each { |vbd|
81
- if env[:xc].VBD.get_userdevice(vbd) == "0"
82
- env[:xc].VBD.set_bootable(vbd, true)
83
- end
84
- }
85
- env[:template] = template_ref
86
- else
87
- (template_ref, template_rec) = template
88
- env[:template] = template_ref
83
+ vbds = env[:xc].VM.get_VBDs(template_ref)
84
+ vbds.each { |vbd|
85
+ if env[:xc].VBD.get_userdevice(vbd) == "0"
86
+ env[:xc].VBD.set_bootable(vbd, true)
87
+ end
88
+ }
89
+ env[:template] = template_ref
90
+ else
91
+ (template_ref, template_rec) = template
92
+ env[:template] = template_ref
93
+ end
89
94
  end
90
-
95
+
91
96
  @app.call(env)
92
97
  end
93
98
  end
@@ -18,6 +18,7 @@ module VagrantPlugins
18
18
 
19
19
  def read_state(xc, session, machine)
20
20
  return :not_created if machine.id.nil?
21
+ return :not_created if not machine.id.start_with?("OpaqueRef")
21
22
 
22
23
  begin
23
24
  result = xc.VM.get_record(machine.id)
@@ -16,78 +16,80 @@ module VagrantPlugins
16
16
  box_name = env[:machine].box.name.to_s
17
17
  box_version = env[:machine].box.version.to_s
18
18
 
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
- }
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
+ }
24
25
 
25
- box_xva_file = env[:machine].box.directory.join('box.xva').to_s
26
+ box_xva_file = env[:machine].box.directory.join('box.xva').to_s
26
27
 
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]
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]
31
32
 
32
- @logger.info("box name=" + env[:machine].box.name.to_s)
33
- @logger.info("box version=" + env[:machine].box.version.to_s)
33
+ @logger.info("box name=" + env[:machine].box.name.to_s)
34
+ @logger.info("box version=" + env[:machine].box.version.to_s)
34
35
 
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")
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")
38
39
 
39
- url = "https://#{hostname}/import?session_id=#{env[:xc].xenapi_session}&task_id=#{task}"
40
+ url = "https://#{hostname}/import?session_id=#{env[:xc].xenapi_session}&task_id=#{task}"
40
41
 
41
- uploader_options = {}
42
- uploader_options[:ui] = env[:ui]
43
- uploader_options[:insecure] = true
42
+ uploader_options = {}
43
+ uploader_options[:ui] = env[:ui]
44
+ uploader_options[:insecure] = true
44
45
 
45
- uploader = MyUtil::Uploader.new(box_xva_file, url, uploader_options)
46
+ uploader = MyUtil::Uploader.new(box_xva_file, url, uploader_options)
46
47
 
47
- begin
48
- uploader.upload!
49
- rescue
50
- env[:xc].task.cancel(task)
51
- end
48
+ begin
49
+ uploader.upload!
50
+ rescue
51
+ env[:xc].task.cancel(task)
52
+ end
52
53
 
53
- task_status = ""
54
+ task_status = ""
54
55
 
55
- begin
56
- sleep(0.2)
57
- task_status = env[:xc].task.get_status(task)
58
- end while task_status == "pending"
56
+ begin
57
+ sleep(0.2)
58
+ task_status = env[:xc].task.get_status(task)
59
+ end while task_status == "pending"
59
60
 
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
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
65
66
 
66
- task_result = env[:xc].task.get_result(task)
67
+ task_result = env[:xc].task.get_result(task)
67
68
 
68
- doc = REXML::Document.new(task_result)
69
+ doc = REXML::Document.new(task_result)
69
70
 
70
- @logger.debug("task_result=\"#{task_result}\"")
71
- template_ref = doc.elements['value/array/data/value'].text
71
+ @logger.debug("task_result=\"#{task_result}\"")
72
+ template_ref = doc.elements['value/array/data/value'].text
72
73
 
73
- @logger.info("template_ref=" + template_ref)
74
+ @logger.info("template_ref=" + template_ref)
74
75
 
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)
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)
79
80
 
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.
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.
83
84
 
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
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
91
93
  end
92
94
 
93
95
  @app.call(env)
@@ -46,7 +46,11 @@ module VagrantPlugins
46
46
  class InsufficientSpace < VagrantXenServerError
47
47
  error_key(:insufficientspace)
48
48
  end
49
+
50
+ class ConnectionError < VagrantXenServerError
51
+ error_key(:connection_error)
52
+ end
53
+
49
54
  end
50
55
  end
51
56
  end
52
-
@@ -20,16 +20,49 @@ module VagrantPlugins
20
20
  end
21
21
 
22
22
  provider('xenserver', parallel: true) do
23
+ # Setup logging and i18n
24
+ setup_logging
23
25
  setup_i18n
24
26
 
25
- require_relative "provider"
27
+ # Return the provider
28
+ require_relative "provider"
26
29
  Provider
27
30
  end
28
31
 
32
+ # This initializes the internationalization strings.
29
33
  def self.setup_i18n
30
34
  I18n.load_path << File.expand_path('locales/en.yml',
31
35
  XenServer.source_root)
32
36
  I18n.reload!
37
+ end
38
+
39
+ # This sets up our log level to be whatever VAGRANT_LOG is.
40
+ def self.setup_logging
41
+ require "log4r"
42
+
43
+ level = nil
44
+ begin
45
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
46
+ rescue NameError
47
+ # This means that the logging constant wasn't found,
48
+ # which is fine. We just keep `level` as `nil`. But
49
+ # we tell the user.
50
+ level = nil
51
+ end
52
+
53
+ # Some constants, such as "true" resolve to booleans, so the
54
+ # above error checking doesn't catch it. This will check to make
55
+ # sure that the log level is an integer, as Log4r requires.
56
+ level = nil if !level.is_a?(Integer)
57
+
58
+ # Set the logging level on all "vagrant" namespaced
59
+ # logs as long as we have a valid level.
60
+ if level
61
+ logger = Log4r::Logger.new("vagrant_xenserver")
62
+ logger.outputters = Log4r::Outputter.stderr
63
+ logger.level = level
64
+ logger = nil
65
+ end
33
66
  end
34
67
  end
35
68
  end
@@ -1,6 +1,6 @@
1
1
  module VagrantPlugins
2
2
  module XenServer
3
- VERSION = "0.0.12"
3
+ VERSION = "0.0.13"
4
4
  end
5
5
  end
6
6
 
data/locales/en.yml CHANGED
@@ -27,3 +27,6 @@ en:
27
27
  There is insufficient space available on the SR.
28
28
  api_error: |-
29
29
  The API call '%{api}' failed with error '%{error}'.
30
+ connection_error: |-
31
+ Failed to connect to the XenServer. Please verify "xs_host" setting is correct.
32
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-xenserver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Ludlam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-24 00:00:00.000000000 Z
11
+ date: 2017-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -134,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
134
  version: '0'
135
135
  requirements: []
136
136
  rubyforge_project:
137
- rubygems_version: 2.5.1
137
+ rubygems_version: 2.5.2
138
138
  signing_key:
139
139
  specification_version: 4
140
140
  summary: Enables Vagrant to manage XenServers.