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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/CHANGELOG.md +40 -0
  4. data/Gemfile +14 -0
  5. data/LICENSE +8 -0
  6. data/README.md +167 -0
  7. data/Rakefile +14 -0
  8. data/example_box/install_wheezy.sh +128 -0
  9. data/example_box/metadata.json +3 -0
  10. data/example_box/mkbox.sh +17 -0
  11. data/lib/vagrant-xenserver/action/clone_disk.rb +30 -0
  12. data/lib/vagrant-xenserver/action/clone_vm.rb +30 -0
  13. data/lib/vagrant-xenserver/action/configure_network.rb +61 -0
  14. data/lib/vagrant-xenserver/action/connect_xs.rb +47 -0
  15. data/lib/vagrant-xenserver/action/create_template.rb +87 -0
  16. data/lib/vagrant-xenserver/action/create_vifs.rb +86 -0
  17. data/lib/vagrant-xenserver/action/create_vm.rb +95 -0
  18. data/lib/vagrant-xenserver/action/destroy_vm.rb +37 -0
  19. data/lib/vagrant-xenserver/action/download_xva.rb +101 -0
  20. data/lib/vagrant-xenserver/action/dummy.rb +16 -0
  21. data/lib/vagrant-xenserver/action/halt_vm.rb +23 -0
  22. data/lib/vagrant-xenserver/action/is_created.rb +20 -0
  23. data/lib/vagrant-xenserver/action/is_running.rb +20 -0
  24. data/lib/vagrant-xenserver/action/is_suspended.rb +20 -0
  25. data/lib/vagrant-xenserver/action/prepare_nfs_settings.rb +85 -0
  26. data/lib/vagrant-xenserver/action/prepare_nfs_valid_ids.rb +17 -0
  27. data/lib/vagrant-xenserver/action/read_ssh_info.rb +97 -0
  28. data/lib/vagrant-xenserver/action/read_state.rb +35 -0
  29. data/lib/vagrant-xenserver/action/resume_vm.rb +30 -0
  30. data/lib/vagrant-xenserver/action/set_vm_params.rb +28 -0
  31. data/lib/vagrant-xenserver/action/start_vm.rb +31 -0
  32. data/lib/vagrant-xenserver/action/suspend_vm.rb +30 -0
  33. data/lib/vagrant-xenserver/action/upload_vhd.rb +164 -0
  34. data/lib/vagrant-xenserver/action/upload_xva.rb +100 -0
  35. data/lib/vagrant-xenserver/action/validate_network.rb +112 -0
  36. data/lib/vagrant-xenserver/action/wait_himn.rb +58 -0
  37. data/lib/vagrant-xenserver/action.rb +272 -0
  38. data/lib/vagrant-xenserver/config.rb +102 -0
  39. data/lib/vagrant-xenserver/errors.rb +68 -0
  40. data/lib/vagrant-xenserver/plugin.rb +70 -0
  41. data/lib/vagrant-xenserver/provider.rb +36 -0
  42. data/lib/vagrant-xenserver/util/exnhandler.rb +49 -0
  43. data/lib/vagrant-xenserver/util/uploader.rb +215 -0
  44. data/lib/vagrant-xenserver/version.rb +6 -0
  45. data/lib/vagrant-xenserver.rb +17 -0
  46. data/locales/en.yml +38 -0
  47. data/vagrant-xenserver.gemspec +27 -0
  48. metadata +173 -0
@@ -0,0 +1,272 @@
1
+ require 'vagrant/action/builder'
2
+ require 'log4r'
3
+
4
+ module VagrantPlugins
5
+ module XenServer
6
+ module Action
7
+ include Vagrant::Action::Builtin
8
+ @logger = Log4r::Logger.new('vagrant::xenserver::action')
9
+ @xvalock = Mutex.new
10
+
11
+ def self.getlock
12
+ @xvalock
13
+ end
14
+
15
+ def self.action_boot
16
+ Vagrant::Action::Builder.new.tap do |b|
17
+ b.use Provision
18
+ b.use PrepareNFSValidIds
19
+ b.use SyncedFolderCleanup
20
+ b.use SyncedFolders
21
+ b.use Call, IsRunning do |env, b2|
22
+ if !env[:result]
23
+ b2.use StartVM
24
+ end
25
+ end
26
+ b.use WaitForHIMNCommunicator
27
+ b.use WaitForCommunicator, ["Running"]
28
+ b.use Call, IsCreated do |env,b2|
29
+ if env[:machine].provider_config.use_himn
30
+ b2.use ConfigureNetwork
31
+ end
32
+ end
33
+ b.use SetHostname
34
+ b.use PrepareNFSSettings
35
+ end
36
+ end
37
+
38
+ def self.action_up
39
+ Vagrant::Action::Builder.new.tap do |b|
40
+ b.use HandleBox
41
+ b.use ConfigValidate
42
+ b.use ConnectXS
43
+ b.use ValidateNetwork
44
+ b.use Call, IsCreated do |env,b2|
45
+ # Create the VM
46
+ if !env[:result]
47
+ b2.use UploadVHD
48
+ b2.use UploadXVA
49
+ b2.use DownloadXVA
50
+ b2.use CreateTemplate
51
+ b2.use CloneVM
52
+ b2.use SetVMParams
53
+ b2.use CreateVIFs
54
+ end
55
+ b2.use action_boot
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.action_halt
61
+ Vagrant::Action::Builder.new.tap do |b|
62
+ b.use ConfigValidate
63
+ b.use Call, IsCreated do |env, b2|
64
+ if !env[:result]
65
+ @logger.info "MessageNotCreated"
66
+ next
67
+ end
68
+ b2.use ConnectXS
69
+ b2.use Call, IsRunning do |env, b3|
70
+ if !env[:result]
71
+ @logger.info "Not running"
72
+ next
73
+ end
74
+ b3.use HaltVM
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def self.action_suspend
81
+ Vagrant::Action::Builder.new.tap do |b|
82
+ b.use ConfigValidate
83
+ b.use Call, IsCreated do |env, b2|
84
+ if !env[:result]
85
+ @logger.info "MessageNotCreated"
86
+ next
87
+ end
88
+ b2.use ConnectXS
89
+ b2.use Call, IsRunning do |env, b3|
90
+ if !env[:result]
91
+ @logger.info "Not running"
92
+ next
93
+ end
94
+ b3.use SuspendVM
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def self.action_resume
101
+ Vagrant::Action::Builder.new.tap do |b|
102
+ b.use ConfigValidate
103
+ b.use Call, IsCreated do |env, b2|
104
+ if !env[:result]
105
+ @logger.info "MessageNotCreated"
106
+ next
107
+ end
108
+ b2.use ConnectXS
109
+ b2.use Call, IsSuspended do |env, b3|
110
+ if !env[:result]
111
+ @logger.info "Not suspended"
112
+ next
113
+ end
114
+ b3.use ResumeVM
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ def self.action_destroy
121
+ Vagrant::Action::Builder.new.tap do |b|
122
+ b.use ConfigValidate
123
+ b.use Call, IsCreated do |env, b2|
124
+ if !env[:result]
125
+ @logger.info "MessageNotCreated"
126
+ next
127
+ end
128
+ b2.use ConnectXS
129
+ b2.use DestroyVM
130
+ b2.use ProvisionerCleanup
131
+ b2.use PrepareNFSValidIds
132
+ b2.use SyncedFolderCleanup
133
+ end
134
+ end
135
+ end
136
+
137
+ def self.action_read_state
138
+ Vagrant::Action::Builder.new.tap do |b|
139
+ b.use ConfigValidate
140
+ b.use ConnectXS
141
+ b.use ReadState
142
+ end
143
+ end
144
+
145
+ def self.action_read_ssh_info
146
+ Vagrant::Action::Builder.new.tap do |b|
147
+ b.use ConfigValidate
148
+ b.use ConnectXS
149
+ b.use ReadSSHInfo
150
+ end
151
+ end
152
+
153
+ def self.action_ssh
154
+ Vagrant::Action::Builder.new.tap do |b|
155
+ @logger.info("XXXXX SSH")
156
+ b.use ConfigValidate
157
+ b.use Call, IsCreated do | env, b2|
158
+ if !env[:result]
159
+ # b2.use MessageNotCreated
160
+ @logger.info("MessageNotCreate")
161
+ next
162
+ end
163
+
164
+ b2.use ConnectXS
165
+ b2.use Call, IsRunning do |env2, b3|
166
+ if !env2[:result]
167
+ #b3.use MessageNotRunning
168
+ @logger.info("MessageNotCreate")
169
+ next
170
+ end
171
+
172
+ b3.use SSHExec
173
+ @logger.info("ssh run")
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ def self.action_ssh_run
180
+ Vagrant::Action::Builder.new.tap do |b|
181
+ @logger.info("XXXXX SSH")
182
+ b.use ConfigValidate
183
+ b.use Call, IsCreated do | env, b2|
184
+ if !env[:result]
185
+ # b2.use MessageNotCreated
186
+ @logger.info("MessageNotCreate")
187
+ next
188
+ end
189
+
190
+ b2.use ConnectXS
191
+ b2.use Call, IsRunning do |env2, b3|
192
+ if !env2[:result]
193
+ #b3.use MessageNotRunning
194
+ @logger.info("MessageNotCreate")
195
+ next
196
+ end
197
+
198
+ b3.use SSHRun
199
+ @logger.info("ssh run")
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ def self.action_provision
206
+ Vagrant::Action::Builder.new.tap do |b|
207
+ @logger.info("XXXXX provision")
208
+ b.use ConfigValidate
209
+ b.use Call, IsCreated do |env, b2|
210
+ if !env[:result]
211
+ @logger.info("MessageNotCreated")
212
+ next
213
+ end
214
+
215
+ b2.use ConnectXS
216
+ b2.use Call, IsRunning do |env2, b3|
217
+ if !env2[:result]
218
+ @logger.info("MessageNotRunning")
219
+ next
220
+ end
221
+
222
+ b3.use Provision
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ def self.action_reload
229
+ Vagrant::Action::Builder.new.tap do |b|
230
+ b.use Call, IsCreated do |env1, b2|
231
+ if !env1[:result]
232
+ b2.use MessageNotCreated
233
+ next
234
+ end
235
+
236
+ b2.use ConfigValidate
237
+ b2.use action_halt
238
+ b2.use action_boot
239
+ end
240
+ end
241
+ end
242
+
243
+ action_root = Pathname.new(File.expand_path('../action', __FILE__))
244
+ autoload :CreateVIFs, action_root.join("create_vifs")
245
+ autoload :ConnectXS, action_root.join("connect_xs")
246
+ autoload :DummyMessage, action_root.join('dummy')
247
+ autoload :ReadState, action_root.join('read_state')
248
+ autoload :IsCreated, action_root.join('is_created')
249
+ autoload :IsRunning, action_root.join('is_running')
250
+ autoload :IsSuspended, action_root.join('is_suspended')
251
+ autoload :UploadXVA, action_root.join('upload_xva')
252
+ autoload :UploadVHD, action_root.join('upload_vhd')
253
+ autoload :CloneDisk, action_root.join('clone_disk')
254
+ autoload :SetVMParams, action_root.join('set_vm_params')
255
+ autoload :CloneVM, action_root.join('clone_vm')
256
+ autoload :CreateTemplate, action_root.join('create_template')
257
+ autoload :DestroyVM, action_root.join('destroy_vm')
258
+ autoload :StartVM, action_root.join('start_vm')
259
+ autoload :HaltVM, action_root.join('halt_vm')
260
+ autoload :SuspendVM, action_root.join('suspend_vm')
261
+ autoload :ResumeVM, action_root.join('resume_vm')
262
+ autoload :ReadSSHInfo, action_root.join('read_ssh_info')
263
+ autoload :PrepareNFSSettings, action_root.join('prepare_nfs_settings')
264
+ autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
265
+ autoload :DownloadXVA, action_root.join('download_xva')
266
+ autoload :WaitForHIMNCommunicator, action_root.join('wait_himn')
267
+ autoload :ValidateNetwork, action_root.join('validate_network')
268
+ autoload :ConfigureNetwork, action_root.join('configure_network')
269
+ end
270
+ end
271
+ end
272
+
@@ -0,0 +1,102 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module XenServer
5
+ class Config < Vagrant.plugin("2", :config)
6
+ # The XenServer host name or IP
7
+ #
8
+ # @return [String]
9
+ attr_accessor :xs_host
10
+
11
+ # The port to communicate with the API on XenServer
12
+ #
13
+ # @return [Int]
14
+ attr_accessor :xs_port
15
+
16
+ # True if the API should be accessed over SSL/TLS
17
+ #
18
+ # @return [Bool]
19
+ attr_accessor :xs_use_ssl
20
+
21
+ # The XenServer username
22
+ #
23
+ # @return [String]
24
+ attr_accessor :xs_username
25
+
26
+ # The XenServer password
27
+ #
28
+ # @return [String]
29
+ attr_accessor :xs_password
30
+
31
+ # Name of the VM
32
+ #
33
+ # @return [String]
34
+ attr_accessor :name
35
+
36
+ # True if the VM should be PV
37
+ #
38
+ # @return [Bool]
39
+ attr_accessor :pv
40
+
41
+ # Timeout for commands sent to XenServer
42
+ #
43
+ # @return [Int]
44
+ attr_accessor :api_timeout
45
+
46
+ # Memory settings
47
+ #
48
+ # @return [Int]
49
+ attr_accessor :memory
50
+
51
+ # XVA URL: If this is set, we'll assume that the XenServer should directly download an XVA from the specified URL
52
+ #
53
+ # @return [String]
54
+ attr_accessor :xva_url
55
+
56
+ # Use HIMN: If this is set, we'll use the host-internal-management-network to connect to the VM (proxying via dom0)
57
+ # Useful if the guest does not have tools installed
58
+ attr_accessor :use_himn
59
+
60
+ def initialize
61
+ @xs_host = UNSET_VALUE
62
+ @xs_port = UNSET_VALUE
63
+ @xs_use_ssl = UNSET_VALUE
64
+ @xs_username = UNSET_VALUE
65
+ @xs_password = UNSET_VALUE
66
+ @name = UNSET_VALUE
67
+ @pv = UNSET_VALUE
68
+ @api_timeout = UNSET_VALUE
69
+ @memory = UNSET_VALUE
70
+ @xva_url = UNSET_VALUE
71
+ @use_himn = UNSET_VALUE
72
+ end
73
+
74
+ def finalize!
75
+ @xs_host = nil if @xs_host == UNSET_VALUE
76
+ @xs_port = 80 if @xs_port == UNSET_VALUE
77
+ @xs_use_ssl = false if @xs_use_ssl == UNSET_VALUE
78
+ @xs_username = nil if @xs_username == UNSET_VALUE
79
+ @xs_password = nil if @xs_password == UNSET_VALUE
80
+ @name = nil if @name == UNSET_VALUE
81
+ @pv = nil if @pv == UNSET_VALUE
82
+ @api_timeout = 60 if @api_timeout == UNSET_VALUE
83
+ @memory = 1024 if @memory == UNSET_VALUE
84
+ @xva_url = nil if @xva_url == UNSET_VALUE
85
+ @use_himn = false if @use_himn == UNSET_VALUE
86
+ end
87
+
88
+ def validate(machine)
89
+ errors = _detected_errors
90
+ errors << I18n.t("vagrant_xenserver.config.host_required") if @xs_host.nil?
91
+ errors << I18n.t("vagrant_xenserver.config.username_required") if @xs_username.nil?
92
+ errors << I18n.t("vagrant_xenserver.config.password_required") if @xs_password.nil?
93
+
94
+ if not (machine.config.vm.networks.any? { |type,options| type == :public_network })
95
+ errors << I18n.t("vagrant_xenserver.config.himn_required") if not @use_himn
96
+ end
97
+ { "XenServer Provider" => errors }
98
+ end
99
+ end
100
+ end
101
+ end
102
+
@@ -0,0 +1,68 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module XenServer
5
+ module Errors
6
+ class VagrantXenServerError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_xenserver.errors")
8
+ end
9
+
10
+ class LoginError < VagrantXenServerError
11
+ error_key(:login_error)
12
+ end
13
+
14
+ class UploaderInterrupted < VagrantXenServerError
15
+ error_key(:uploader_interrupted)
16
+ end
17
+
18
+ class UploaderError < VagrantXenServerError
19
+ error_key(:uploader_error)
20
+ end
21
+
22
+ class APIError < VagrantXenServerError
23
+ error_key(:api_error)
24
+ end
25
+
26
+ class UnknownOS < VagrantXenServerError
27
+ error_key(:unknown_os)
28
+ end
29
+
30
+ class QemuImgError < VagrantXenServerError
31
+ error_key(:qemuimg_error)
32
+ end
33
+
34
+ class NoDefaultSR < VagrantXenServerError
35
+ error_key(:nodefaultsr_error)
36
+ end
37
+
38
+ class NoHostsAvailable < VagrantXenServerError
39
+ error_key(:nohostsavailable_error)
40
+ end
41
+
42
+ class Import404 < VagrantXenServerError
43
+ error_key(:import404)
44
+ end
45
+
46
+ class InvalidNetwork < VagrantXenServerError
47
+ error_key(:invalid_network)
48
+ end
49
+
50
+ class InvalidInterface < VagrantXenServerError
51
+ error_key(:invalid_interface)
52
+ end
53
+
54
+ class InsufficientSpace < VagrantXenServerError
55
+ error_key(:insufficientspace)
56
+ end
57
+
58
+ class ConnectionError < VagrantXenServerError
59
+ error_key(:connection_error)
60
+ end
61
+
62
+ class HIMNCommunicatorError < VagrantXenServerError
63
+ error_key(:himn_communicator_error)
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,70 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant XenServer plugin must be run within Vagrant."
5
+ end
6
+
7
+
8
+ module VagrantPlugins
9
+ module XenServer
10
+ class Plugin < Vagrant.plugin("2")
11
+ name "XenServer provider"
12
+ description <<-DESC
13
+ This plugin installs a provider that allows Vagrant to manage
14
+ virtual machines hosted on a XenServer.
15
+ DESC
16
+
17
+ config('xenserver', :provider) do
18
+ require_relative "config"
19
+ Config
20
+ end
21
+
22
+ provider('xenserver', parallel: true) do
23
+ # Setup logging and i18n
24
+ setup_logging
25
+ setup_i18n
26
+
27
+ # Return the provider
28
+ require_relative "provider"
29
+ Provider
30
+ end
31
+
32
+ # This initializes the internationalization strings.
33
+ def self.setup_i18n
34
+ I18n.load_path << File.expand_path('locales/en.yml',
35
+ XenServer.source_root)
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
66
+ end
67
+ end
68
+ end
69
+ end
70
+
@@ -0,0 +1,36 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module XenServer
5
+ class Provider < Vagrant.plugin("2", :provider)
6
+ def initialize(machine)
7
+ @machine = machine
8
+ end
9
+
10
+ def action(name)
11
+ action_method = "action_#{name}"
12
+ return Action.send(action_method) if Action.respond_to?(action_method)
13
+ nil
14
+ end
15
+
16
+ def ssh_info
17
+ env = @machine.action('read_ssh_info')
18
+ env[:machine_ssh_info]
19
+ end
20
+
21
+ def state
22
+ env = @machine.action("read_state")
23
+
24
+ state_id = env[:machine_state_id]
25
+
26
+ Vagrant::MachineState.new(state_id, state_id, state_id)
27
+ end
28
+
29
+ def to_s
30
+ id = @machine.id.nil? ? "new" : @machine.id
31
+ "XenServer (#{id})"
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,49 @@
1
+ # Handle the errors thrown by XenServer
2
+ require "json"
3
+
4
+ module VagrantPlugins
5
+ module XenServer
6
+ module MyUtil
7
+ class Exnhandler
8
+
9
+ def self.def(api,error)
10
+ # Default case: raise generic API error
11
+ raise Errors::APIError,
12
+ api: api,
13
+ error: String(error)
14
+ end
15
+
16
+ def self.handle(api,error)
17
+ case error[0]
18
+ when "IMPORT_ERROR"
19
+ case error[1]
20
+ when "404 Not Found"
21
+ raise Errors::Import404
22
+ else
23
+ Exnhandler.def(api,error)
24
+ end
25
+ when "SR_BACKEND_FAILURE_44"
26
+ raise Errors::InsufficientSpace
27
+ else
28
+ raise Errors::APIError,
29
+ api: api,
30
+ error: String(error)
31
+ end
32
+ end
33
+
34
+ def self.handle_xenapiexn(api,e,logger)
35
+ case e
36
+ when XenApi::Errors::SRFull
37
+ raise Errors::InsufficientSpace
38
+ when XenApi::Errors::GenericError
39
+ # Grotesque hack - get the error array back by parsing the string
40
+ # representation as JSON. Bleurgh!
41
+ self.handle(api,JSON.parse(e.message))
42
+ else
43
+ self.handle(api,e)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end