vagrant-vcenter 0.0.2.pre.dev

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