vagrant-xenserver 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
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