vagrant-vcenter 0.0.2.pre.dev

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 (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +34 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE +20 -0
  6. data/README.md +5 -0
  7. data/Rakefile +17 -0
  8. data/example_box/README.md +13 -0
  9. data/example_box/Vagrantfile +6 -0
  10. data/example_box/metadata.json +1 -0
  11. data/lib/vagrant-vcenter.rb +18 -0
  12. data/lib/vagrant-vcenter/action.rb +232 -0
  13. data/lib/vagrant-vcenter/action/announce_ssh_exec.rb +19 -0
  14. data/lib/vagrant-vcenter/action/build_vm.rb +130 -0
  15. data/lib/vagrant-vcenter/action/connect_vcenter.rb +37 -0
  16. data/lib/vagrant-vcenter/action/destroy.rb +29 -0
  17. data/lib/vagrant-vcenter/action/disconnect_vcenter.rb +29 -0
  18. data/lib/vagrant-vcenter/action/inventory_check.rb +132 -0
  19. data/lib/vagrant-vcenter/action/is_created.rb +26 -0
  20. data/lib/vagrant-vcenter/action/is_paused.rb +23 -0
  21. data/lib/vagrant-vcenter/action/is_running.rb +23 -0
  22. data/lib/vagrant-vcenter/action/message_already_running.rb +17 -0
  23. data/lib/vagrant-vcenter/action/message_cannot_suspend.rb +19 -0
  24. data/lib/vagrant-vcenter/action/message_not_created.rb +17 -0
  25. data/lib/vagrant-vcenter/action/message_will_not_destroy.rb +18 -0
  26. data/lib/vagrant-vcenter/action/power_off.rb +30 -0
  27. data/lib/vagrant-vcenter/action/power_on.rb +30 -0
  28. data/lib/vagrant-vcenter/action/read_ssh_info.rb +37 -0
  29. data/lib/vagrant-vcenter/action/read_state.rb +52 -0
  30. data/lib/vagrant-vcenter/action/resume.rb +30 -0
  31. data/lib/vagrant-vcenter/action/suspend.rb +30 -0
  32. data/lib/vagrant-vcenter/action/sync_folders.rb +135 -0
  33. data/lib/vagrant-vcenter/config.rb +92 -0
  34. data/lib/vagrant-vcenter/errors.rb +88 -0
  35. data/lib/vagrant-vcenter/plugin.rb +67 -0
  36. data/lib/vagrant-vcenter/provider.rb +46 -0
  37. data/lib/vagrant-vcenter/version.rb +6 -0
  38. data/locales/en.yml +50 -0
  39. data/vagrant-vcenter.gemspec +29 -0
  40. metadata +194 -0
@@ -0,0 +1,37 @@
1
+ module VagrantPlugins
2
+ module VCenter
3
+ module Action
4
+ # This class reads the IP info for the VM that the Vagrant provider is
5
+ # managing using VMware Tools.
6
+ class ReadSSHInfo
7
+ # FIXME: More work needed here for vCenter logic (vApp, VM IPs, etc.)
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new('vagrant_vcenter::action::read_ssh_info')
12
+ end
13
+
14
+ def call(env)
15
+ env[:machine_ssh_info] = read_ssh_info(env)
16
+
17
+ @app.call env
18
+ end
19
+
20
+ def read_ssh_info(env)
21
+ return nil if env[:machine].id.nil?
22
+
23
+ config = env[:machine].provider_config
24
+ # FIXME: Raise a correct exception
25
+ dc = config.vcenter_cnx.serviceInstance.find_datacenter(
26
+ config.datacenter_name) or abort 'datacenter not found'
27
+ root_vm_folder = dc.vmFolder
28
+ vm = root_vm_folder.findByUuid(env[:machine].id)
29
+
30
+ @logger.debug("IP Address: #{vm.guest.ipAddress}")
31
+
32
+ { :host => vm.guest.ipAddress, :port => 22 }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,52 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module VCenter
5
+ module Action
6
+ # This Class read the power state of the VM that Vagrant is managing.
7
+ class ReadState
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new('vagrant_vcenter::action::read_state')
11
+ end
12
+
13
+ def call(env)
14
+ env[:machine_state_id] = read_state(env)
15
+ @app.call env
16
+ end
17
+
18
+ def read_state(env)
19
+ # FIXME: this part needs some cleanup
20
+ config = env[:machine].provider_config
21
+
22
+ # FIXME: Raise a correct exception
23
+ dc = config.vcenter_cnx.serviceInstance.find_datacenter(
24
+ config.datacenter_name) or abort 'datacenter not found'
25
+
26
+ root_vm_folder = dc.vmFolder
27
+
28
+ vm = root_vm_folder.findByUuid(env[:machine].id)
29
+
30
+ @logger.debug("Current power state: #{vm.runtime.powerState}")
31
+ vm_name = env[:machine].name
32
+
33
+ if env[:machine].id.nil?
34
+ @logger.info("VM [#{vm_name}] is not created yet")
35
+ return :not_created
36
+ end
37
+
38
+ if vm.runtime.powerState == 'poweredOff'
39
+ @logger.info("VM [#{vm_name}] is stopped")
40
+ return :stopped
41
+ elsif vm.runtime.powerState == 'poweredOn'
42
+ @logger.info("VM [#{vm_name}] is running")
43
+ return :running
44
+ elsif vm.runtime.powerState == 'suspended'
45
+ @logger.info("VM [#{vm_name}] is suspended")
46
+ return :suspended
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,30 @@
1
+ require 'i18n'
2
+
3
+ module VagrantPlugins
4
+ module VCenter
5
+ module Action
6
+ # This class resumes the VM when it's suspended.
7
+ class Resume
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new('vagrant_vcenter::action::resume')
11
+ end
12
+
13
+ def call(env)
14
+ config = env[:machine].provider_config
15
+ # FIXME: Raise a correct exception
16
+ dc = config.vcenter_cnx.serviceInstance.find_datacenter(
17
+ config.datacenter_name) or abort 'datacenter not found'
18
+ root_vm_folder = dc.vmFolder
19
+ vm = root_vm_folder.findByUuid(env[:machine].id)
20
+
21
+ # Poweroff VM
22
+ env[:ui].info('Powering on VM...')
23
+ vm.PowerOnVM_Task.wait_for_completion
24
+
25
+ @app.call env
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'i18n'
2
+
3
+ module VagrantPlugins
4
+ module VCenter
5
+ module Action
6
+ # This class suspends the VM when it's powered on.
7
+ class Suspend
8
+ def initialize(app, env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new('vagrant_vcenter::action::suspend')
11
+ end
12
+
13
+ def call(env)
14
+ config = env[:machine].provider_config
15
+ # FIXME: Raise a correct exception
16
+ dc = config.vcenter_cnx.serviceInstance.find_datacenter(
17
+ config.datacenter_name) or abort 'datacenter not found'
18
+ root_vm_folder = dc.vmFolder
19
+ vm = root_vm_folder.findByUuid(env[:machine].id)
20
+
21
+ # Poweroff VM
22
+ env[:ui].info('Suspending VM...')
23
+ vm.SuspendVM_Task.wait_for_completion
24
+
25
+ @app.call env
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,135 @@
1
+ # The MIT License (MIT)
2
+ # Copyright (c) 2013 Mitchell Hashimoto
3
+
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to
6
+ # deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
+ # sell copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
+ # IN THE SOFTWARE.
21
+
22
+ require 'log4r'
23
+ require 'vagrant/util/subprocess'
24
+ require 'vagrant/util/scoped_hash_override'
25
+ require 'vagrant/util/which'
26
+
27
+ module VagrantPlugins
28
+ module VCenter
29
+ module Action
30
+ # This class syncs Vagrant folders using RSYNC, this code has been ported
31
+ # from vagrant-aws (https://github.com/mitchellh/vagrant-aws)
32
+ class SyncFolders
33
+ include Vagrant::Util::ScopedHashOverride
34
+
35
+ def initialize(app, env)
36
+ @app = app
37
+ @logger = Log4r::Logger.new('vagrant_vcenter::action::sync_folders')
38
+ end
39
+
40
+ def call(env)
41
+ @app.call(env)
42
+
43
+ ssh_info = env[:machine].ssh_info
44
+
45
+ unless Vagrant::Util::Which.which('rsync')
46
+ env[:ui].warn(I18n.t('vagrant_vcenter.sync.rsync_not_found_warning',
47
+ :side => 'host'))
48
+ return
49
+ end
50
+
51
+ if env[:machine].communicate.execute('which rsync',
52
+ :error_check => false) != 0
53
+ env[:ui].warn(I18n.t('vagrant_vcenter.sync.rsync_not_found_warning',
54
+ :side => 'guest'))
55
+ return
56
+ end
57
+
58
+ env[:machine].config.vm.synced_folders.each do |id, data|
59
+ data = scoped_hash_override(data, :vCenter)
60
+
61
+ # Ignore disabled shared folders
62
+ next if data[:disabled]
63
+
64
+ hostpath = File.expand_path(data[:hostpath], env[:root_path])
65
+ guestpath = data[:guestpath]
66
+
67
+ # Make sure there is a trailing slash on the host path to
68
+ # avoid creating an additional directory with rsync
69
+ hostpath = "#{hostpath}/" if hostpath !~ /\/$/
70
+
71
+ # on windows rsync.exe requires cygdrive-style paths
72
+ if Vagrant::Util::Platform.windows?
73
+ hostpath = hostpath.gsub(/^(\w):/) { "/cygdrive/\1" }
74
+ end
75
+
76
+ env[:ui].info(I18n.t('vagrant_vcenter.sync.rsync_folder',
77
+ :hostpath => hostpath,
78
+ :guestpath => guestpath))
79
+
80
+ # Create the host path if it doesn't exist and option flag is set
81
+ if data[:create]
82
+ begin
83
+ FileUtils.mkdir_p(hostpath)
84
+ rescue => err
85
+ raise Errors::MkdirError,
86
+ :hostpath => hostpath,
87
+ :err => err
88
+ end
89
+ end
90
+
91
+ # Create the guest path
92
+ env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
93
+ env[:machine].communicate.sudo(
94
+ "chown -R #{ssh_info[:username]} '#{guestpath}'")
95
+
96
+ # collect rsync excludes specified :rsync_excludes=>['path1',...]
97
+ # in synced_folder options
98
+ excludes = ['.vagrant/', 'Vagrantfile',
99
+ *Array(data[:rsync_excludes])].uniq
100
+
101
+ # Rsync over to the guest path using the SSH info
102
+ command = [
103
+ 'rsync', '--verbose', '--archive', '-z',
104
+ *excludes.map { |e|['--exclude', e] }.flatten,
105
+ '-e', "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no " +
106
+ "#{ssh_key_options(ssh_info)}", hostpath,
107
+ "#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
108
+
109
+ # we need to fix permissions when using rsync.exe on windows, see
110
+ # http://stackoverflow.com/questions/5798807/rsync-permission-
111
+ # denied-created-directories-have-no-permissions
112
+ if Vagrant::Util::Platform.windows?
113
+ command.insert(1, '--chmod', 'ugo=rwX')
114
+ end
115
+
116
+ r = Vagrant::Util::Subprocess.execute(*command)
117
+ if r.exit_code != 0
118
+ fail Errors::RsyncError,
119
+ :guestpath => guestpath,
120
+ :hostpath => hostpath,
121
+ :stderr => r.stderr
122
+ end
123
+ end
124
+ end
125
+
126
+ private
127
+
128
+ def ssh_key_options(ssh_info)
129
+ # Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
130
+ Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,92 @@
1
+ require 'vagrant'
2
+
3
+ module VagrantPlugins
4
+ module VCenter
5
+ # Initialize Provider configuration parameters.
6
+ class Config < Vagrant.plugin('2', :config)
7
+ # login attributes
8
+
9
+ # The vCenter hostname
10
+ #
11
+ # @return [String]
12
+ attr_accessor :hostname
13
+
14
+ # The username used to log in
15
+ #
16
+ # @return [String]
17
+ attr_accessor :username
18
+
19
+ # The password used to log in
20
+ #
21
+ # @return [String]
22
+ attr_accessor :password
23
+
24
+ # WIP on these
25
+
26
+ # Catalog Name where the item resides
27
+ #
28
+ # @return [String]
29
+ attr_accessor :folder_name
30
+
31
+ # Catalog Name where the item resides
32
+ #
33
+ # @return [String]
34
+ attr_accessor :template_folder_name
35
+
36
+ # Catalog Item to be used as a template
37
+ #
38
+ # @return [String]
39
+ attr_accessor :datastore_name
40
+
41
+ # Virtual Data Center to be used
42
+ #
43
+ # @return [String]
44
+ attr_accessor :datacenter_name
45
+
46
+ # Virtual Data Center to be used
47
+ #
48
+ # @return [String]
49
+ attr_accessor :computer_name
50
+
51
+ # Virtual Data Center Network to be used
52
+ #
53
+ # @return [String]
54
+ attr_accessor :network_name
55
+
56
+ # Virtual Data Center Network to be used
57
+ #
58
+ # @return [Bool]
59
+ attr_accessor :linked_clones
60
+
61
+ ##
62
+ ## vCenter config runtime values
63
+ ##
64
+
65
+ # connection handle
66
+ attr_accessor :vcenter_cnx
67
+ attr_accessor :template_id
68
+
69
+ def validate(machine)
70
+ errors = _detected_errors
71
+
72
+ # TODO: add blank?
73
+ errors <<
74
+ I18n.t('vagrant_vcenter.config.hostname') if hostname.nil?
75
+ errors <<
76
+ I18n.t('vagrant_vcenter.config.username') if username.nil?
77
+ errors <<
78
+ I18n.t('vagrant_vcenter.config.password') if password.nil?
79
+ errors <<
80
+ I18n.t('vagrant_vcenter.config.datastore_name') if datastore_name.nil?
81
+ errors <<
82
+ I18n.t('vagrant_vcenter.config.datacenter_name') if datacenter_name.nil?
83
+ errors <<
84
+ I18n.t('vagrant_vcenter.config.computer_name') if computer_name.nil?
85
+ errors <<
86
+ I18n.t('vagrant_vcenter.config.network_name') if network_name.nil?
87
+
88
+ { 'vCenter Provider' => errors }
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,88 @@
1
+ require 'vagrant'
2
+
3
+ module VagrantPlugins
4
+ module VCenter
5
+ module Errors
6
+ # Initialize main error class.
7
+ class VCenterError < Vagrant::Errors::VagrantError
8
+ error_namespace('vagrant_vcenter.errors')
9
+ end
10
+ # Set key for Rsync errors.
11
+ class RsyncError < VCenterError
12
+ error_key(:rsync_error)
13
+ end
14
+ # Set key for Mkdir errors.
15
+ class MkdirError < VCenterError
16
+ error_key(:mkdir_error)
17
+ end
18
+ # Set key for VCenterOldVersion errors.
19
+ class VCenterOldVersion < VCenterError
20
+ error_key(:vcenter_old_version)
21
+ end
22
+ # Set key for CatalogAddError errors.
23
+ class CatalogAddError < VCenterError
24
+ error_key(:catalog_add_error)
25
+ end
26
+ # Set key for HostNotFound errors.
27
+ class HostNotFound < VCenterError
28
+ error_key(:host_not_found)
29
+ end
30
+ # Set key for HostRedirect errors.
31
+ class HostRedirect < VCenterError
32
+ error_key(:host_redirect)
33
+ end
34
+ # Set key for UnauthorizedAccess errors.
35
+ class UnauthorizedAccess < VCenterError
36
+ error_key(:unauthorized_access)
37
+ end
38
+ # Set key for StopVAppError errors.
39
+ class StopVAppError < VCenterError
40
+ error_key(:stop_vapp_error)
41
+ end
42
+ # Set key for ComposeVAppError errors.
43
+ class ComposeVAppError < VCenterError
44
+ error_key(:compose_vapp_error)
45
+ end
46
+ # Set key for InvalidNetSpecification errors.
47
+ class InvalidNetSpecification < VCenterError
48
+ error_key(:invalid_network_specification)
49
+ end
50
+ # Set key for ForwardPortCollision errors.
51
+ class ForwardPortCollision < VCenterError
52
+ error_key(:forward_port_collision)
53
+ end
54
+ # Set key for SubnetErrors errors.
55
+ class SubnetErrors < VCenterError
56
+ error_namespace('vagrant_Vcenter.errors.subnet_errors')
57
+ end
58
+ # Set key for InvalidSubnet errors.
59
+ class InvalidSubnet < SubnetErrors
60
+ error_key(:invalid_subnet)
61
+ end
62
+ # Set key for SubnetTooSmall errors.
63
+ class SubnetTooSmall < SubnetErrors
64
+ error_key(:subnet_too_small)
65
+ end
66
+ # Set key for RestError errors.
67
+ class RestError < VCenterError
68
+ error_namespace('vagrant_Vcenter.errors.rest_errors')
69
+ end
70
+ # Set key for ObjectNotFound errors.
71
+ class ObjectNotFound < RestError
72
+ error_key(:object_not_found)
73
+ end
74
+ # Set key for InvalidConfigError errors.
75
+ class InvalidConfigError < RestError
76
+ error_key(:invalid_config_error)
77
+ end
78
+ # Set key for InvalidStateError errors.
79
+ class InvalidStateError < RestError
80
+ error_key(:invalid_state_error)
81
+ end
82
+ # Set key for SyncError errors.
83
+ class SyncError < VCenterError
84
+ error_key(:sync_error)
85
+ end
86
+ end
87
+ end
88
+ end