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