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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +103 -25
  3. data/example_box/install_wheezy.sh +128 -0
  4. data/example_box/mkbox.sh +17 -0
  5. data/lib/vagrant-xenserver/action.rb +14 -4
  6. data/lib/vagrant-xenserver/action/clone_disk.rb +1 -1
  7. data/lib/vagrant-xenserver/action/clone_vm.rb +35 -0
  8. data/lib/vagrant-xenserver/action/connect_xs.rb +19 -11
  9. data/lib/vagrant-xenserver/action/create_template.rb +86 -0
  10. data/lib/vagrant-xenserver/action/create_vifs.rb +44 -23
  11. data/lib/vagrant-xenserver/action/create_vm.rb +14 -10
  12. data/lib/vagrant-xenserver/action/destroy_vm.rb +9 -6
  13. data/lib/vagrant-xenserver/action/download_xva.rb +96 -0
  14. data/lib/vagrant-xenserver/action/halt_vm.rb +1 -5
  15. data/lib/vagrant-xenserver/action/prepare_nfs_valid_ids.rb +1 -1
  16. data/lib/vagrant-xenserver/action/read_ssh_info.rb +48 -12
  17. data/lib/vagrant-xenserver/action/read_state.rb +4 -5
  18. data/lib/vagrant-xenserver/action/resume_vm.rb +3 -3
  19. data/lib/vagrant-xenserver/action/set_vm_params.rb +28 -0
  20. data/lib/vagrant-xenserver/action/start_vm.rb +7 -2
  21. data/lib/vagrant-xenserver/action/suspend_vm.rb +3 -3
  22. data/lib/vagrant-xenserver/action/upload_vhd.rb +130 -115
  23. data/lib/vagrant-xenserver/action/upload_xva.rb +63 -50
  24. data/lib/vagrant-xenserver/config.rb +45 -0
  25. data/lib/vagrant-xenserver/errors.rb +20 -0
  26. data/lib/vagrant-xenserver/plugin.rb +8 -0
  27. data/lib/vagrant-xenserver/util/exnhandler.rb +49 -0
  28. data/lib/vagrant-xenserver/version.rb +1 -1
  29. data/locales/en.yml +20 -1
  30. data/vagrant-xenserver.gemspec +1 -0
  31. metadata +24 -5
  32. data/lib/vagrant-xenserver/action/maybe_upload_disk.rb +0 -85
  33. 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
- result = xc.call("VM.get_record",session,machine.id)
23
-
24
- if result["Status"] != "Success"
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].call("Async.VM.resume",env[:session],myvm,false,false)['Value']
17
- while env[:xc].call("task.get_status",env[:session],resume_task)['Value'] == 'pending' do
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].call("task.get_status",env[:session],resume_task)['Value']
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
- env[:xc].call("VM.start",env[:session],myvm,false,false)
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].call("Async.VM.suspend",env[:session],myvm)['Value']
17
- while env[:xc].call("task.get_status",env[:session],suspend_task)['Value'] == 'pending' do
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].call("task.get_status",env[:session],suspend_task)['Value']
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 "xmlrpc/client"
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
- vdi_ref_rec = vdis.find { |reference,record|
37
- @logger.info(record['tags'].to_s)
38
- record['tags'].include?(vdi_tag)
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
- virtual_size = disk_info['virtual-size']
52
- @logger.info("virtual_size=#{virtual_size}")
53
- pool=env[:xc].call("pool.get_all",env[:session])['Value'][0]
54
- default_sr=env[:xc].call("pool.get_default_SR",env[:session],pool)['Value']
55
- @logger.info("default_SR="+default_sr)
56
- vdi_record = {
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
- tag_result=env[:xc].call("VDI.add_tags",env[:session],vdi_result,vdi_tag)
133
- @logger.info("task_result=" + tag_result.to_s)
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
- env[:box_vdi] = vdi_result
136
- end
137
- else
138
- (reference,record) = vdi_ref_rec
139
- env[:box_vdi] = reference
140
- @logger.info("box_vdi="+reference)
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
- #box_image_file = env[:machine].box.directory.join('export.xva').to_s
17
- box_image_file = "/home/jludlam/devel/vagrant-xenserver/test.xva"
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
- task = task_result["Value"]
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
- url = "https://#{hostname}/import?session_id=#{session}&task_id=#{task}"
25
+ box_xva_file = env[:machine].box.directory.join('box.xva').to_s
35
26
 
36
- uploader_options = {}
37
- uploader_options[:ui] = env[:ui]
38
- uploader_options[:insecure] = true
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
- uploader = MyUtil::Uploader.new(box_image_file, url, uploader_options)
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
- begin
43
- uploader.upload!
44
- rescue Errors::UploaderInterrupted
45
- env[:ui].info(I18n.t("vagrant.xenserver.action.upload_xva.interrupted"))
46
- raise
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
- task_status = ""
41
+ uploader_options = {}
42
+ uploader_options[:ui] = env[:ui]
43
+ uploader_options[:insecure] = true
50
44
 
51
- begin
52
- sleep(0.2)
53
- task_status_result = env[:xc].call("task.get_status",env[:session],task)
54
- if task_status_result["Status"] != "Success"
55
- raise Errors::APIError
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
- @logger.info("task_status="+task_status)
53
+ task_status = ""
61
54
 
62
- if task_status != "success"
63
- raise Errors::APIError
64
- end
55
+ begin
56
+ sleep(0.2)
57
+ task_status = env[:xc].task.get_status(task)
58
+ end while task_status == "pending"
65
59
 
66
- task_result_result = env[:xc].call("task.get_result",env[:session],task)
67
- if task_result_result["Status"] != "Success"
68
- raise Errors::APIError
69
- end
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
- task_result = task_result_result["Value"]
66
+ task_result = env[:xc].task.get_result(task)
72
67
 
73
- doc = REXML::Document.new(task_result)
68
+ doc = REXML::Document.new(task_result)
74
69
 
75
- doc.elements.each('value/array/data/value') do |ele|
76
- @logger.info("ele=" + ele.text)
77
- end
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
- @logger.info("task_result=" + task_result)
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