vagrant-xenserver-jc 0.0.13

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