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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +34 -0
- data/Gemfile +7 -0
- data/LICENSE +20 -0
- data/README.md +5 -0
- data/Rakefile +17 -0
- data/example_box/README.md +13 -0
- data/example_box/Vagrantfile +6 -0
- data/example_box/metadata.json +1 -0
- data/lib/vagrant-vcenter.rb +18 -0
- data/lib/vagrant-vcenter/action.rb +232 -0
- data/lib/vagrant-vcenter/action/announce_ssh_exec.rb +19 -0
- data/lib/vagrant-vcenter/action/build_vm.rb +130 -0
- data/lib/vagrant-vcenter/action/connect_vcenter.rb +37 -0
- data/lib/vagrant-vcenter/action/destroy.rb +29 -0
- data/lib/vagrant-vcenter/action/disconnect_vcenter.rb +29 -0
- data/lib/vagrant-vcenter/action/inventory_check.rb +132 -0
- data/lib/vagrant-vcenter/action/is_created.rb +26 -0
- data/lib/vagrant-vcenter/action/is_paused.rb +23 -0
- data/lib/vagrant-vcenter/action/is_running.rb +23 -0
- data/lib/vagrant-vcenter/action/message_already_running.rb +17 -0
- data/lib/vagrant-vcenter/action/message_cannot_suspend.rb +19 -0
- data/lib/vagrant-vcenter/action/message_not_created.rb +17 -0
- data/lib/vagrant-vcenter/action/message_will_not_destroy.rb +18 -0
- data/lib/vagrant-vcenter/action/power_off.rb +30 -0
- data/lib/vagrant-vcenter/action/power_on.rb +30 -0
- data/lib/vagrant-vcenter/action/read_ssh_info.rb +37 -0
- data/lib/vagrant-vcenter/action/read_state.rb +52 -0
- data/lib/vagrant-vcenter/action/resume.rb +30 -0
- data/lib/vagrant-vcenter/action/suspend.rb +30 -0
- data/lib/vagrant-vcenter/action/sync_folders.rb +135 -0
- data/lib/vagrant-vcenter/config.rb +92 -0
- data/lib/vagrant-vcenter/errors.rb +88 -0
- data/lib/vagrant-vcenter/plugin.rb +67 -0
- data/lib/vagrant-vcenter/provider.rb +46 -0
- data/lib/vagrant-vcenter/version.rb +6 -0
- data/locales/en.yml +50 -0
- data/vagrant-vcenter.gemspec +29 -0
- 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
|