vagrant-parallels 1.5.1 → 1.6.0
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 +4 -4
- data/.travis.yml +7 -4
- data/CHANGELOG.md +33 -0
- data/Gemfile +2 -2
- data/README.md +1 -1
- data/debug.log +1237 -1
- data/lib/vagrant-parallels/action.rb +8 -0
- data/lib/vagrant-parallels/action/box_register.rb +113 -0
- data/lib/vagrant-parallels/action/box_unregister.rb +43 -0
- data/lib/vagrant-parallels/action/export.rb +36 -35
- data/lib/vagrant-parallels/action/forward_ports.rb +32 -18
- data/lib/vagrant-parallels/action/import.rb +59 -106
- data/lib/vagrant-parallels/action/network.rb +17 -13
- data/lib/vagrant-parallels/action/prepare_clone_snapshot.rb +67 -0
- data/lib/vagrant-parallels/action/set_name.rb +1 -1
- data/lib/vagrant-parallels/action/snapshot_delete.rb +25 -0
- data/lib/vagrant-parallels/action/snapshot_restore.rb +23 -0
- data/lib/vagrant-parallels/action/snapshot_save.rb +23 -0
- data/lib/vagrant-parallels/cap.rb +63 -0
- data/lib/vagrant-parallels/config.rb +7 -3
- data/lib/vagrant-parallels/driver/base.rb +61 -28
- data/lib/vagrant-parallels/driver/meta.rb +20 -10
- data/lib/vagrant-parallels/driver/pd_11.rb +0 -21
- data/lib/vagrant-parallels/errors.rb +14 -6
- data/lib/vagrant-parallels/guest_cap/darwin/install_parallels_tools.rb +34 -0
- data/lib/vagrant-parallels/plugin.rb +23 -8
- data/lib/vagrant-parallels/version.rb +1 -1
- data/locales/en.yml +31 -17
- data/test/acceptance/provider/linked_clone_spec.rb +6 -2
- data/test/acceptance/skeletons/linked_clone/Vagrantfile +1 -1
- data/test/unit/base.rb +1 -0
- data/test/unit/cap_test.rb +96 -0
- data/test/unit/support/shared/pd_driver_examples.rb +7 -10
- metadata +12 -6
- data/lib/vagrant-parallels/cap/forwarded_ports.rb +0 -22
- data/lib/vagrant-parallels/cap/host_address.rb +0 -15
- data/lib/vagrant-parallels/cap/nic_mac_addresses.rb +0 -17
- data/lib/vagrant-parallels/cap/public_address.rb +0 -15
@@ -14,6 +14,11 @@ module VagrantPlugins
|
|
14
14
|
# We use forwardable to do all our driver forwarding
|
15
15
|
extend Forwardable
|
16
16
|
|
17
|
+
# We cache the Parallels Desktop version here once we have one,
|
18
|
+
# since during the execution of Vagrant, it likely doesn't change.
|
19
|
+
@@version = nil
|
20
|
+
@@version_lock = Mutex.new
|
21
|
+
|
17
22
|
# The UUID of the virtual machine we represent
|
18
23
|
attr_reader :uuid
|
19
24
|
|
@@ -29,23 +34,26 @@ module VagrantPlugins
|
|
29
34
|
|
30
35
|
# Read and assign the version of Parallels Desktop we know which
|
31
36
|
# specific driver to instantiate.
|
32
|
-
|
33
|
-
|
37
|
+
@@version_lock.synchronize do
|
38
|
+
@@version = read_version
|
39
|
+
end
|
40
|
+
|
34
41
|
# Instantiate the proper version driver for Parallels Desktop
|
35
|
-
@logger.debug("Finding driver for Parallels Desktop version: #{
|
42
|
+
@logger.debug("Finding driver for Parallels Desktop version: #{@@version}")
|
36
43
|
|
44
|
+
major_ver = @@version.split('.').first.to_i
|
37
45
|
driver_klass =
|
38
|
-
case
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
case major_ver
|
47
|
+
when 1..7 then raise Errors::ParallelsUnsupportedVersion
|
48
|
+
when 8 then PD_8
|
49
|
+
when 9 then PD_9
|
50
|
+
when 10 then PD_10
|
51
|
+
else PD_11
|
44
52
|
end
|
45
53
|
|
46
54
|
# Starting since PD 11 only Pro and Business editions have CLI
|
47
55
|
# functionality and can be used with Vagrant.
|
48
|
-
if
|
56
|
+
if major_ver >= 11
|
49
57
|
edition = read_edition
|
50
58
|
if !edition || !%w(any pro business).include?(edition)
|
51
59
|
raise Errors::ParallelsUnsupportedEdition
|
@@ -54,6 +62,7 @@ module VagrantPlugins
|
|
54
62
|
|
55
63
|
@logger.info("Using Parallels driver: #{driver_klass}")
|
56
64
|
@driver = driver_klass.new(@uuid)
|
65
|
+
@version = @@version
|
57
66
|
|
58
67
|
if @uuid
|
59
68
|
# Verify the VM exists, and if it doesn't, then don't worry
|
@@ -77,6 +86,7 @@ module VagrantPlugins
|
|
77
86
|
:forward_ports,
|
78
87
|
:halt,
|
79
88
|
:clone_vm,
|
89
|
+
:list_snapshots,
|
80
90
|
:read_bridged_interfaces,
|
81
91
|
:read_current_snapshot,
|
82
92
|
:read_forwarded_ports,
|
@@ -14,27 +14,6 @@ module VagrantPlugins
|
|
14
14
|
|
15
15
|
@logger = Log4r::Logger.new('vagrant_parallels::driver::pd_11')
|
16
16
|
end
|
17
|
-
|
18
|
-
def create_snapshot(uuid, options)
|
19
|
-
args = ['snapshot', uuid]
|
20
|
-
args.concat(['--name', options[:name]]) if options[:name]
|
21
|
-
args.concat(['--description', options[:desc]]) if options[:desc]
|
22
|
-
|
23
|
-
stdout = execute_prlctl(*args)
|
24
|
-
if stdout =~ /\{([\w-]+)\}/
|
25
|
-
return $1
|
26
|
-
end
|
27
|
-
|
28
|
-
raise Errors::SnapshotIdNotDetected, stdout: stdout
|
29
|
-
end
|
30
|
-
|
31
|
-
def read_current_snapshot(uuid)
|
32
|
-
if execute_prlctl('snapshot-list', uuid) =~ /\*\{([\w-]+)\}/
|
33
|
-
return $1
|
34
|
-
end
|
35
|
-
|
36
|
-
nil
|
37
|
-
end
|
38
17
|
end
|
39
18
|
end
|
40
19
|
end
|
@@ -7,6 +7,14 @@ module VagrantPlugins
|
|
7
7
|
error_namespace('vagrant_parallels.errors')
|
8
8
|
end
|
9
9
|
|
10
|
+
class BoxImageNotFound < VagrantParallelsError
|
11
|
+
error_key(:box_image_not_found)
|
12
|
+
end
|
13
|
+
|
14
|
+
class BoxIDNotFound < VagrantParallelsError
|
15
|
+
error_key(:box_id_not_found)
|
16
|
+
end
|
17
|
+
|
10
18
|
class DhcpLeasesNotAccessible < VagrantParallelsError
|
11
19
|
error_key(:dhcp_leases_file_not_accessible)
|
12
20
|
end
|
@@ -51,10 +59,6 @@ module VagrantPlugins
|
|
51
59
|
error_key(:parallels_tools_iso_not_found)
|
52
60
|
end
|
53
61
|
|
54
|
-
class ParallelsTplNameNotFound < VagrantParallelsError
|
55
|
-
error_key(:parallels_tpl_name_not_found)
|
56
|
-
end
|
57
|
-
|
58
62
|
class ParallelsVMOptionNotFound < VagrantParallelsError
|
59
63
|
error_key(:parallels_vm_option_not_found)
|
60
64
|
end
|
@@ -75,8 +79,12 @@ module VagrantPlugins
|
|
75
79
|
error_key(:snapshot_id_not_detected)
|
76
80
|
end
|
77
81
|
|
78
|
-
class
|
79
|
-
error_key(:
|
82
|
+
class SnapshotNotFound < VagrantParallelsError
|
83
|
+
error_key(:snapshot_not_found)
|
84
|
+
end
|
85
|
+
|
86
|
+
class VMCloneFailure < VagrantParallelsError
|
87
|
+
error_key(:vm_clone_failure)
|
80
88
|
end
|
81
89
|
|
82
90
|
class VMNameExists < VagrantParallelsError
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Parallels
|
3
|
+
module GuestDarwinCap
|
4
|
+
class InstallParallelsTools
|
5
|
+
|
6
|
+
def self.install_parallels_tools(machine)
|
7
|
+
machine.communicate.tap do |comm|
|
8
|
+
tools_iso_path = File.expand_path(
|
9
|
+
machine.provider.driver.read_guest_tools_iso_path('darwin'),
|
10
|
+
machine.env.root_path
|
11
|
+
)
|
12
|
+
remote_file = '/tmp/prl-tools-mac.iso'
|
13
|
+
mount_point = "/media/prl-tools-lin_#{rand(100000)}/"
|
14
|
+
|
15
|
+
comm.upload(tools_iso_path, remote_file)
|
16
|
+
|
17
|
+
# Create mount point directory if needed
|
18
|
+
if !comm.test("test -d \"#{mount_point}\"", :sudo => true)
|
19
|
+
comm.sudo("mkdir -p \"#{mount_point}\"")
|
20
|
+
end
|
21
|
+
|
22
|
+
# Mount ISO and install Parallels Tools
|
23
|
+
comm.sudo("hdiutil attach #{remote_file} -mountpoint #{mount_point}")
|
24
|
+
comm.sudo("installer -pkg '#{mount_point}/Install.app/Contents/Resources/Install.mpkg' -target /")
|
25
|
+
comm.sudo("hdiutil detach '#{mount_point}'")
|
26
|
+
|
27
|
+
comm.sudo("rm -Rf \"#{mount_point}\"")
|
28
|
+
comm.sudo("rm -f \"#{remote_file}\"")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -6,8 +6,8 @@ end
|
|
6
6
|
|
7
7
|
# This is a sanity check to make sure no one is attempting to install
|
8
8
|
# this into an early Vagrant version.
|
9
|
-
if Vagrant::VERSION < '1.
|
10
|
-
raise 'The Vagrant Parallels plugin is only compatible with Vagrant 1.
|
9
|
+
if Gem::Version.new(Vagrant::VERSION).release < Gem::Version.new('1.8.0')
|
10
|
+
raise 'The installed version of Vagrant Parallels plugin is only compatible with Vagrant 1.8+'
|
11
11
|
end
|
12
12
|
|
13
13
|
module VagrantPlugins
|
@@ -33,6 +33,11 @@ module VagrantPlugins
|
|
33
33
|
Config
|
34
34
|
end
|
35
35
|
|
36
|
+
guest_capability(:darwin, :install_parallels_tools) do
|
37
|
+
require_relative 'guest_cap/darwin/install_parallels_tools'
|
38
|
+
GuestDarwinCap::InstallParallelsTools
|
39
|
+
end
|
40
|
+
|
36
41
|
guest_capability(:darwin, :mount_parallels_shared_folder) do
|
37
42
|
require_relative 'guest_cap/darwin/mount_parallels_shared_folder'
|
38
43
|
GuestDarwinCap::MountParallelsSharedFolder
|
@@ -64,18 +69,28 @@ module VagrantPlugins
|
|
64
69
|
end
|
65
70
|
|
66
71
|
provider_capability(:parallels, :public_address) do
|
67
|
-
require_relative 'cap
|
68
|
-
Cap
|
72
|
+
require_relative 'cap'
|
73
|
+
Cap
|
74
|
+
end
|
75
|
+
|
76
|
+
provider_capability(:parallels, :forwarded_ports) do
|
77
|
+
require_relative 'cap'
|
78
|
+
Cap
|
69
79
|
end
|
70
80
|
|
71
81
|
provider_capability(:parallels, :host_address) do
|
72
|
-
require_relative 'cap
|
73
|
-
Cap
|
82
|
+
require_relative 'cap'
|
83
|
+
Cap
|
74
84
|
end
|
75
85
|
|
76
86
|
provider_capability(:parallels, :nic_mac_addresses) do
|
77
|
-
require_relative 'cap
|
78
|
-
Cap
|
87
|
+
require_relative 'cap'
|
88
|
+
Cap
|
89
|
+
end
|
90
|
+
|
91
|
+
provider_capability(:parallels, :snapshot_list) do
|
92
|
+
require_relative 'cap'
|
93
|
+
Cap
|
79
94
|
end
|
80
95
|
|
81
96
|
synced_folder(:parallels) do
|
data/locales/en.yml
CHANGED
@@ -7,6 +7,18 @@ en:
|
|
7
7
|
# Translations for exception classes
|
8
8
|
#-------------------------------------------------------------------------------
|
9
9
|
errors:
|
10
|
+
box_id_not_found: |-
|
11
|
+
Parallels provider couldn't fetch the box image ID. This is usually because
|
12
|
+
the "config.pvs" file is corrupted or doesn't exist. Please remove the box,
|
13
|
+
re-add it, and try again.
|
14
|
+
|
15
|
+
Box: "%{name}"
|
16
|
+
Box VM config: "%{config}"
|
17
|
+
|
18
|
+
box_image_not_found: |-
|
19
|
+
Parallels VM image (*.pvm) could not be found in the directory of
|
20
|
+
'%{name}' box. This is usually because the image has been removed manually.
|
21
|
+
Please remove the box, re-add it, and try again.
|
10
22
|
dhcp_leases_file_not_accessible: |-
|
11
23
|
Parallels DHCP leases file is not accessible. The Parallels provider
|
12
24
|
uses it to detect an IP address of virtual machine. This file must be
|
@@ -67,12 +79,6 @@ en:
|
|
67
79
|
reinstall Parallels Desktop.
|
68
80
|
|
69
81
|
Expected ISO path: "%{iso_path}"
|
70
|
-
parallels_tpl_name_not_found: |-
|
71
|
-
The VM import failed! Template name not found. Please verify that
|
72
|
-
the box you're using is not corrupted and try again.
|
73
|
-
|
74
|
-
Template config path: "%{config_path}"
|
75
|
-
|
76
82
|
parallels_vm_option_not_found: |-
|
77
83
|
Could not find a required option of Parallels Desktop virtual machine:
|
78
84
|
%{vm_option}
|
@@ -95,17 +101,22 @@ en:
|
|
95
101
|
Desktop for Mac. Please, be aware while choosing the edition to upgrade to.
|
96
102
|
snapshot_id_not_detected: |-
|
97
103
|
ID of the newly created shapshod could not be detected. This is an
|
98
|
-
internal error that users should never see. Please report a bug
|
104
|
+
internal error that users should never see. Please report a bug to
|
105
|
+
Parallels provider.
|
99
106
|
|
100
107
|
stdout: %{stdout}
|
108
|
+
snapshot_not_found: |-
|
109
|
+
The 'linked_clone_snapshot' specified could not be found. Please double
|
110
|
+
check and try again.
|
111
|
+
|
112
|
+
Snapshot ID: %{snapshot}
|
101
113
|
shared_adapter_not_found: |-
|
102
114
|
Shared network adapter was not found in your virtual machine configuration.
|
103
115
|
It is required to communicate with VM and forward ports. Please check
|
104
116
|
network configuration in your Vagrantfile.
|
105
|
-
|
106
|
-
The VM
|
117
|
+
vm_clone_failure: |-
|
118
|
+
The VM cloning failed! Please ensure that the box you're using is not
|
107
119
|
corrupted and try again.
|
108
|
-
|
109
120
|
vm_name_exists: |-
|
110
121
|
Parallels Desktop virtual machine with the name '%{name}' already exists.
|
111
122
|
Please use another name or delete the machine with the existing
|
@@ -170,6 +181,12 @@ en:
|
|
170
181
|
#-------------------------------------------------------------------------------
|
171
182
|
actions:
|
172
183
|
vm:
|
184
|
+
box:
|
185
|
+
register: Registering VM image from the base box '%{name}'...
|
186
|
+
unregister: Unregistering the box VM image...
|
187
|
+
clone:
|
188
|
+
full: Cloning new virtual machine...
|
189
|
+
linked: Creating new virtual machine as a linked clone...
|
173
190
|
handle_guest_tools:
|
174
191
|
cant_install: |-
|
175
192
|
Vagrant doesn't support installing Parallels Tools for the guest OS
|
@@ -181,24 +198,21 @@ en:
|
|
181
198
|
Installing the proper version of Parallels Tools. This may take a few minutes...
|
182
199
|
not_detected: |-
|
183
200
|
Parallels Tools were not detected on this VM! They are required
|
184
|
-
for
|
185
|
-
|
186
|
-
|
187
|
-
reload your VM.
|
201
|
+
for shared folders, time sync and more. If shared folders are not
|
202
|
+
working on this machine, please install Parallels Tools within the
|
203
|
+
virtual machine and reload your VM.
|
188
204
|
rebooting: |-
|
189
205
|
Parallels Tools have been installed. Rebooting the VM...
|
190
206
|
outdated: |-
|
191
207
|
Parallels Tools installed on this VM are outdated! In most cases
|
192
208
|
this is fine but in rare cases it can cause things such as shared
|
193
209
|
folders to not work properly. If you see shared folder errors,
|
194
|
-
please update Parallels Tools within the virtual machine and
|
210
|
+
please update Parallels Tools within the virtual machine and
|
195
211
|
reload your VM.
|
196
212
|
export:
|
197
213
|
compacting: Compacting exported HDDs...
|
198
214
|
forward_ports:
|
199
215
|
forwarding_entry: |-
|
200
216
|
%{guest_port} => %{host_port}
|
201
|
-
import:
|
202
|
-
importing_linked: Importing base box '%{name}' as a linked clone...
|
203
217
|
sane_defaults:
|
204
218
|
setting: Setting the default configuration for VM...
|
@@ -10,7 +10,6 @@ shared_examples 'provider/linked_clone' do |provider, options|
|
|
10
10
|
before do
|
11
11
|
environment.skeleton('linked_clone')
|
12
12
|
assert_execute('vagrant', 'box', 'add', 'basic', options[:box])
|
13
|
-
assert_execute('vagrant', 'up', "--provider=#{provider}")
|
14
13
|
end
|
15
14
|
|
16
15
|
after do
|
@@ -18,7 +17,12 @@ shared_examples 'provider/linked_clone' do |provider, options|
|
|
18
17
|
end
|
19
18
|
|
20
19
|
it 'creates machine as linked clone' do
|
21
|
-
status('Test: machine is
|
20
|
+
status('Test: machine is created as a linked clone')
|
21
|
+
result = execute('vagrant', 'up', "--provider=#{provider}")
|
22
|
+
expect(result).to exit_with(0)
|
23
|
+
expect(result.stdout).to match(/linked clone/)
|
24
|
+
|
25
|
+
status('Test: machine is available by ssh')
|
22
26
|
result = execute('vagrant', 'ssh', '-c', 'echo foo')
|
23
27
|
expect(result).to exit_with(0)
|
24
28
|
expect(result.stdout).to match(/foo\n$/)
|
data/test/unit/base.rb
CHANGED
@@ -0,0 +1,96 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
require 'vagrant-parallels/cap'
|
4
|
+
|
5
|
+
describe VagrantPlugins::Parallels::Cap do
|
6
|
+
include_context 'vagrant-unit'
|
7
|
+
|
8
|
+
let(:iso_env) do
|
9
|
+
# We have to create a Vagrantfile so there is a root path
|
10
|
+
env = isolated_environment
|
11
|
+
env.vagrantfile('')
|
12
|
+
env.create_vagrant_env
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:machine) do
|
16
|
+
iso_env.machine(iso_env.machine_names[0], :dummy).tap do |m|
|
17
|
+
m.provider.stub(driver: driver)
|
18
|
+
m.stub(state: state)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:driver) { double('driver') }
|
23
|
+
let(:state) { double('state', id: :running) }
|
24
|
+
|
25
|
+
describe '#forwarded_ports' do
|
26
|
+
it 'returns all the forwarded ports' do
|
27
|
+
allow(driver).to receive(:read_forwarded_ports).and_return([
|
28
|
+
{ hostport: 123, guestport: 456 },
|
29
|
+
{ hostport: 245, guestport: 245 }
|
30
|
+
])
|
31
|
+
|
32
|
+
expect(described_class.forwarded_ports(machine)).to eq({
|
33
|
+
123 => 456,
|
34
|
+
245 => 245,
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns nil when the machine is not running' do
|
39
|
+
allow(state).to receive(:id).and_return(:stopped)
|
40
|
+
expect(described_class.forwarded_ports(machine)).to be(nil)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#host_address' do
|
45
|
+
it "returns host's IP of Shared interface" do
|
46
|
+
allow(driver).to receive(:read_shared_interface).and_return(ip: '1.2.3.4')
|
47
|
+
expect(described_class.host_address(machine)).to eq('1.2.3.4')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#nic_mac_addresses' do
|
52
|
+
it 'returns a hash with MAC addresses' do
|
53
|
+
allow(driver).to receive(:read_mac_addresses).and_return(
|
54
|
+
['001A2B3C4D5E', '005E4D3C2B1A'])
|
55
|
+
expect(described_class.nic_mac_addresses(machine)).to eq({
|
56
|
+
1 => '001A2B3C4D5E',
|
57
|
+
2 => '005E4D3C2B1A'
|
58
|
+
})
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns an empty hash when there are no NICs' do
|
62
|
+
allow(driver).to receive(:read_mac_addresses).and_return([])
|
63
|
+
expect(described_class.nic_mac_addresses(machine)).to eq({})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#public_address' do
|
68
|
+
it "returns VM's IP" do
|
69
|
+
allow(machine).to receive(:ssh_info).and_return(host: '1.2.3.4')
|
70
|
+
expect(described_class.public_address(machine)).to eq('1.2.3.4')
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns nil when the machine is not running" do
|
74
|
+
allow(state).to receive(:id).and_return(:stopped)
|
75
|
+
expect(described_class.public_address(machine)).to be(nil)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns nil when there is no ssh info" do
|
79
|
+
allow(machine).to receive(:ssh_info).and_return(nil)
|
80
|
+
expect(described_class.public_address(machine)).to be(nil)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#snapshot_list' do
|
85
|
+
it 'returns a list of snapshots' do
|
86
|
+
allow(machine).to receive(:id).and_return('foo')
|
87
|
+
allow(driver).to receive(:list_snapshots).with('foo').and_return({
|
88
|
+
'snap_name_1' => 'snap_uuid_1',
|
89
|
+
'snap_name_2' => 'snap_uuid_2'
|
90
|
+
})
|
91
|
+
|
92
|
+
expect(described_class.snapshot_list(machine)).to eq(
|
93
|
+
['snap_name_1', 'snap_name_2'])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|