vagrant-parallels 0.1.2 → 0.1.3

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.
@@ -9,9 +9,16 @@ module VagrantPlugins
9
9
  def call(env)
10
10
  raise Vagrant::Errors::VMBaseMacNotSpecified if !env[:machine].config.vm.base_mac
11
11
 
12
- # Create the proc which we want to use to modify the virtual machine
13
- env[:ui].info I18n.t("vagrant.actions.vm.match_mac.matching")
14
- env[:machine].provider.driver.set_mac_address(env[:machine].config.vm.base_mac)
12
+ env[:ui].info I18n.t("vagrant_parallels.actions.vm.match_mac.matching")
13
+
14
+ base_mac = env[:machine].config.vm.base_mac
15
+ # Generate new base mac if the specified address is already in use
16
+ if env[:machine].provider.driver.mac_in_use?(base_mac)
17
+ env[:ui].info I18n.t("vagrant_parallels.actions.vm.match_mac.generate")
18
+ env[:machine].provider.driver.set_mac_address('auto')
19
+ else
20
+ env[:machine].provider.driver.set_mac_address(base_mac)
21
+ end
15
22
 
16
23
  @app.call(env)
17
24
  end
@@ -40,6 +40,7 @@ module VagrantPlugins
40
40
 
41
41
  def compact(uuid=nil)
42
42
  uuid ||= @uuid
43
+ # TODO: VM can have more than one hdd!
43
44
  path_to_hdd = read_settings(uuid).fetch("Hardware", {}).fetch("hdd0", {}).fetch("image", nil)
44
45
  raw('prl_disk_tool', 'compact', '--hdd', path_to_hdd) do |type, data|
45
46
  lines = data.split("\r")
@@ -80,7 +81,9 @@ module VagrantPlugins
80
81
  end
81
82
 
82
83
  def clear_shared_folders
83
- read_settings.fetch("Host Shared Folders", {}).keys.drop(1).each do |folder|
84
+ shf = read_settings.fetch("Host Shared Folders", {}).keys
85
+ shf.delete("enabled")
86
+ shf.each do |folder|
84
87
  execute("set", @uuid, "--shf-host-del", folder)
85
88
  end
86
89
  end
@@ -214,6 +217,18 @@ module VagrantPlugins
214
217
  end
215
218
  end
216
219
 
220
+
221
+ def mac_in_use?(mac)
222
+ all_macs_in_use = []
223
+ read_all_info.each do |vm|
224
+ all_macs_in_use << vm.fetch('Hardware', {}).fetch('net0',{}).fetch('mac', '')
225
+ end
226
+
227
+ valid_mac = mac.upcase.tr('^A-F0-9', '')
228
+
229
+ all_macs_in_use.include?(valid_mac)
230
+ end
231
+
217
232
  # Returns a hash of all UUIDs assigned to VMs and templates currently
218
233
  # known by Parallels. Keys are 'name' values
219
234
  #
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Parallels
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3"
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -890,7 +890,10 @@ en:
890
890
  The VM import failed! Try running `prlctl import` on the box file
891
891
  manually for more verbose error output.
892
892
  match_mac:
893
- matching: Matching MAC address for NAT networking...
893
+ generate: |-
894
+ The specified base MAC is already in use. Generating a new unique MAC
895
+ address for Shared network...
896
+ matching: Matching MAC address for Shared network...
894
897
  no_base_mac: |-
895
898
  No base MAC address was specified. This is required for the NAT networking
896
899
  to work properly (and hence port forwarding, SSH, etc.). Specifying this
@@ -0,0 +1,3 @@
1
+ # This installs the tasks that help with gem creation and
2
+ # publishing.
3
+ Bundler::GemHelper.install_tasks
data/tasks/test.rake ADDED
@@ -0,0 +1,12 @@
1
+ require 'rake/testtask'
2
+ require 'rspec/core/rake_task'
3
+
4
+ namespace :test do
5
+ RSpec::Core::RakeTask.new(:unit) do |t|
6
+ t.pattern = "test/unit/**/*_test.rb"
7
+ end
8
+
9
+ RSpec::Core::RakeTask.new(:acceptance) do |t|
10
+ t.pattern = "test/acceptance/**/*_test.rb"
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+
4
+ require "log4r"
5
+
6
+ require "support/tempdir"
7
+
8
+ # This class manages an isolated environment for Vagrant to
9
+ # run in. It creates a temporary directory to act as the
10
+ # working directory as well as sets a custom home directory.
11
+ #
12
+ # This class also provides various helpers to create Vagrantfiles,
13
+ # boxes, etc.
14
+ class IsolatedEnvironment
15
+ attr_reader :homedir
16
+ attr_reader :workdir
17
+
18
+ # Initializes an isolated environment. You can pass in some
19
+ # options here to configure runing custom applications in place
20
+ # of others as well as specifying environmental variables.
21
+ #
22
+ # @param [Hash] apps A mapping of application name (such as "vagrant")
23
+ # to an alternate full path to the binary to run.
24
+ # @param [Hash] env Additional environmental variables to inject
25
+ # into the execution environments.
26
+ def initialize
27
+ @logger = Log4r::Logger.new("test::isolated_environment")
28
+
29
+ # Create a temporary directory for our work
30
+ @tempdir = Tempdir.new("vagrant")
31
+ @logger.info("Initialize isolated environment: #{@tempdir.path}")
32
+
33
+ # Setup the home and working directories
34
+ @homedir = Pathname.new(File.join(@tempdir.path, "home"))
35
+ @workdir = Pathname.new(File.join(@tempdir.path, "work"))
36
+
37
+ @homedir.mkdir
38
+ @workdir.mkdir
39
+ end
40
+
41
+ # This closes the environment by cleaning it up.
42
+ def close
43
+ @logger.info("Removing isolated environment: #{@tempdir.path}")
44
+ FileUtils.rm_rf(@tempdir.path)
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ require 'fileutils'
2
+ require 'tempfile'
3
+
4
+ # This class provides an easy way of creating a temporary
5
+ # directory and having it removed when the application exits.
6
+ class Tempdir
7
+ attr_reader :path
8
+
9
+ def initialize(basename="vagrant")
10
+ @path = nil
11
+
12
+ # Loop and attempt to create a temporary directory until
13
+ # it succeeds.
14
+ while @path.nil?
15
+ file = Tempfile.new(basename)
16
+ @path = file.path
17
+ file.unlink
18
+
19
+ begin
20
+ Dir.mkdir(@path)
21
+ rescue
22
+ @path = nil
23
+ end
24
+ end
25
+
26
+ # Setup a finalizer to delete the directory. This is the same way
27
+ # that Tempfile and friends do this...
28
+ @cleanup_proc = lambda do
29
+ FileUtils.rm_rf(@path) if File.directory?(@path)
30
+ end
31
+
32
+ ObjectSpace.define_finalizer(self, @cleanup_proc)
33
+ end
34
+
35
+ # This deletes the temporary directory.
36
+ def unlink
37
+ # Delete the directory
38
+ @cleanup_proc.call
39
+
40
+ # Undefine the finalizer since we're all cleaned up
41
+ ObjectSpace.undefine_finalizer(self)
42
+ end
43
+ end
data/test/unit/base.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "rubygems"
2
+ require "rspec/autorun"
3
+
4
+ # Require Vagrant itself so we can reference the proper
5
+ # classes to test.
6
+ require "vagrant"
7
+ require 'vagrant-parallels'
8
+
9
+ # Add the test directory to the load path
10
+ $:.unshift File.expand_path("../../", __FILE__)
11
+
12
+ # Load in helpers
13
+ require "support/tempdir"
14
+ require "unit/support/shared/parallels_context"
15
+
16
+ # Do not buffer output
17
+ $stdout.sync = true
18
+ $stderr.sync = true
19
+
20
+ # Configure RSpec
21
+ RSpec.configure do |c|
22
+ c.expect_with :rspec, :stdlib
23
+ end
24
+
25
+ # Configure VAGRANT_CWD so that the tests never find an actual
26
+ # Vagrantfile anywhere, or at least this minimizes those chances.
27
+ ENV["VAGRANT_CWD"] = Tempdir.new.path
@@ -0,0 +1,138 @@
1
+ require_relative "../base"
2
+
3
+ describe VagrantPlugins::Parallels::Driver::PrlCtl do
4
+ include_context "parallels"
5
+
6
+ subject { VagrantPlugins::Parallels::Driver::PrlCtl.new(uuid) }
7
+
8
+ describe "compact" do
9
+ it "compacts the VM disk images" do
10
+ pending "Should have possibility to compact more than one hdd"
11
+ end
12
+ end
13
+
14
+ describe "create_host_only_network" do
15
+ it "creates host-only NIC"
16
+ end
17
+
18
+ describe "export" do
19
+ tpl_name = "new_template_name"
20
+ tpl_uuid = "12345-hfgs-3456-hste"
21
+
22
+ it "exports VM to template" do
23
+ subject.stub(:read_settings).with(tpl_name).
24
+ and_return({"ID" => tpl_uuid})
25
+
26
+ subprocess.should_receive(:execute).
27
+ with("prlctl", "clone", uuid, "--name", an_instance_of(String), "--template", "--dst",
28
+ an_instance_of(String), an_instance_of(Hash)).
29
+ and_return(subprocess_result(stdout: "The VM has been successfully cloned"))
30
+ subject.export("/path/to/template", tpl_name).should == tpl_uuid
31
+ end
32
+ end
33
+
34
+ describe "clear_shared_folders" do
35
+ shf_hash = {"enabled" => true, "shf_name_1" => {}, "shf_name_2" => {}}
36
+ it "deletes every shared folder assigned to the VM" do
37
+ subject.stub(:read_settings).and_return({"Host Shared Folders" => shf_hash})
38
+
39
+ subprocess.should_receive(:execute).exactly(2).times.
40
+ with("prlctl", "set", uuid, "--shf-host-del", an_instance_of(String), an_instance_of(Hash)).
41
+ and_return(subprocess_result(stdout: "Shared folder deleted"))
42
+ subject.clear_shared_folders
43
+ end
44
+ end
45
+
46
+ describe "halt" do
47
+ it "stops the VM" do
48
+ subprocess.should_receive(:execute).
49
+ with("prlctl", "stop", uuid, an_instance_of(Hash)).
50
+ and_return(subprocess_result(stdout: "VM has been halted gracefully"))
51
+ subject.halt
52
+ end
53
+
54
+ it "stops the VM force" do
55
+ subprocess.should_receive(:execute).
56
+ with("prlctl", "stop", uuid, "--kill", an_instance_of(Hash)).
57
+ and_return(subprocess_result(stdout: "VM has been halted forcibly"))
58
+ subject.halt(force=true)
59
+ end
60
+ end
61
+
62
+ describe "mac_in_use?" do
63
+ vm_1 = {
64
+ 'Hardware' => {
65
+ 'net0' => {'mac' => '001C42BB5901'},
66
+ 'net1' => {'mac' => '001C42BB5902'},
67
+ }
68
+ }
69
+ vm_2 = {
70
+ 'Hardware' => {
71
+ 'net0' => {'mac' => '001C42BB5903'},
72
+ 'net1' => {'mac' => '001C42BB5904'},
73
+ }
74
+ }
75
+
76
+ it "checks the MAC address is already in use" do
77
+ subject.stub(:read_all_info).and_return([vm_1, vm_2])
78
+
79
+ subject.mac_in_use?('00:1c:42:bb:59:01').should be_true
80
+ subject.mac_in_use?('00:1c:42:bb:59:02').should be_false
81
+ subject.mac_in_use?('00:1c:42:bb:59:03').should be_true
82
+ subject.mac_in_use?('00:1c:42:bb:59:04').should be_false
83
+ end
84
+ end
85
+
86
+ describe "set_mac_address" do
87
+ it "sets base MAC address to the Shared network adapter" do
88
+ subprocess.should_receive(:execute).exactly(2).times.
89
+ with("prlctl", "set", uuid, '--device-set', 'net0', '--type', 'shared', '--mac',
90
+ an_instance_of(String), an_instance_of(Hash)).
91
+ and_return(subprocess_result(stdout: "Settings applied"))
92
+
93
+ subject.set_mac_address('001C42DD5902')
94
+ subject.set_mac_address('auto')
95
+ end
96
+ end
97
+
98
+ describe "start" do
99
+ it "starts the VM" do
100
+ subprocess.should_receive(:execute).
101
+ with("prlctl", "start", uuid, an_instance_of(Hash)).
102
+ and_return(subprocess_result(stdout: "VM started"))
103
+ subject.start
104
+ end
105
+ end
106
+
107
+ describe "suspend" do
108
+ it "suspends the VM" do
109
+ subprocess.should_receive(:execute).
110
+ with("prlctl", "suspend", uuid, an_instance_of(Hash)).
111
+ and_return(subprocess_result(stdout: "VM suspended"))
112
+ subject.suspend
113
+ end
114
+ end
115
+
116
+ describe "unregister" do
117
+ it "suspends the VM" do
118
+ subprocess.should_receive(:execute).
119
+ with("prlctl", "unregister", an_instance_of(String), an_instance_of(Hash)).
120
+ and_return(subprocess_result(stdout: "Specified VM unregistered"))
121
+ subject.unregister("template_or_vm_uuid")
122
+ end
123
+ end
124
+
125
+ describe "version" do
126
+ it "parses the version from output" do
127
+ subject.version.should match(/(#{parallels_version}[\d\.]+)/)
128
+ end
129
+
130
+ it "rises ParallelsInstallIncomplete exception when output is invalid" do
131
+ subprocess.should_receive(:execute).
132
+ with("prlctl", "--version", an_instance_of(Hash)).
133
+ and_return(subprocess_result(stdout: "Some incorrect value has been returned!"))
134
+ expect { subject.version }.
135
+ to raise_error(VagrantPlugins::Parallels::Errors::ParallelsInstallIncomplete)
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,30 @@
1
+ shared_context "parallels" do
2
+ let(:parallels_context) { true }
3
+ let(:uuid) { "9876-dcba-8765-hgfe" }
4
+ let(:parallels_version) { "9" }
5
+ let(:subprocess) { double("Vagrant::Util::Subprocess") }
6
+
7
+ # this is a helper that returns a duck type suitable from a system command
8
+ # execution; allows setting exit_code, stdout, and stderr in stubs.
9
+ def subprocess_result(options={})
10
+ defaults = {exit_code: 0, stdout: "", stderr: ""}
11
+ double("subprocess_result", defaults.merge(options))
12
+ end
13
+
14
+ before do
15
+ # we don't want unit tests to ever run commands on the system; so we wire
16
+ # in a double to ensure any unexpected messages raise exceptions
17
+ stub_const("Vagrant::Util::Subprocess", subprocess)
18
+
19
+ # drivers will blow up on instantiation if they cannot determine the
20
+ # Parallels Desktop version, so wire this stub in automatically
21
+ subprocess.stub(:execute).
22
+ with("prlctl", "--version", an_instance_of(Hash)).
23
+ and_return(subprocess_result(stdout: "prlctl version #{parallels_version}.23456.987654"))
24
+
25
+ # drivers also call vm_exists? during init;
26
+ subprocess.stub(:execute).
27
+ with("prlctl", "list", kind_of(String), "--info", "--json", kind_of(Hash)).
28
+ and_return(subprocess_result(exit_code: 0))
29
+ end
30
+ end
@@ -18,9 +18,7 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_development_dependency "bundler", "~> 1.3"
20
20
  spec.add_development_dependency "rake"
21
- spec.add_development_dependency "rspec-core", "~> 2.12.2"
22
- spec.add_development_dependency "rspec-expectations", "~> 2.12.1"
23
- spec.add_development_dependency "rspec-mocks", "~> 2.12.1"
21
+ spec.add_development_dependency "rspec", "~> 2.14.0"
24
22
 
25
23
  # The following block of code determines the files that should be included
26
24
  # in the gem. It does this by reading all the files in the directory where
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-parallels
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-20 00:00:00.000000000 Z
12
+ date: 2013-12-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -44,13 +44,13 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
46
  - !ruby/object:Gem::Dependency
47
- name: rspec-core
47
+ name: rspec
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 2.12.2
53
+ version: 2.14.0
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,39 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 2.12.2
62
- - !ruby/object:Gem::Dependency
63
- name: rspec-expectations
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: 2.12.1
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: 2.12.1
78
- - !ruby/object:Gem::Dependency
79
- name: rspec-mocks
80
- requirement: !ruby/object:Gem::Requirement
81
- none: false
82
- requirements:
83
- - - ~>
84
- - !ruby/object:Gem::Version
85
- version: 2.12.1
86
- type: :development
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ~>
92
- - !ruby/object:Gem::Version
93
- version: 2.12.1
61
+ version: 2.14.0
94
62
  description: Enables Vagrant to manage Parallels machines.
95
63
  email:
96
64
  - yshahin@gmail.com
@@ -148,10 +116,15 @@ files:
148
116
  - locales/en.yml
149
117
  - Rakefile
150
118
  - README.md
151
- - spec/vagrant-parallels/setup_spec.rb
119
+ - tasks/bundler.rake
120
+ - tasks/test.rake
121
+ - test/support/isolated_environment.rb
122
+ - test/support/tempdir.rb
123
+ - test/unit/base.rb
124
+ - test/unit/driver/prl_ctl_test.rb
125
+ - test/unit/support/shared/parallels_context.rb
152
126
  - vagrant-parallels.gemspec
153
127
  - .gitignore
154
- - .ruby-gemset
155
128
  - .travis.yml
156
129
  homepage: http://github.com/yshahin/vagrant-parallels
157
130
  licenses:
@@ -168,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
141
  version: '0'
169
142
  segments:
170
143
  - 0
171
- hash: -845057650540824242
144
+ hash: 1018017984449213160
172
145
  required_rubygems_version: !ruby/object:Gem::Requirement
173
146
  none: false
174
147
  requirements: