diff --git a/Gemfile b/Gemfile index 740783bf..5ebdb1bd 100644 --- a/Gemfile +++ b/Gemfile @@ -7,8 +7,5 @@ group :development do # We depend on Vagrant for development, but we don't add it as a # gem dependency because we expect to be installed within the # Vagrant environment itself using `vagrant plugin`. - gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.4.1' - gem 'vagrant-spec', git: "https://github.com/mitchellh/vagrant-spec.git" - gem 'debugger-xml' - gem 'pry' + gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.4.3' end diff --git a/lib/vagrant-parallels/action.rb b/lib/vagrant-parallels/action.rb index 44208ba7..f3c60aa7 100644 --- a/lib/vagrant-parallels/action.rb +++ b/lib/vagrant-parallels/action.rb @@ -12,6 +12,7 @@ module Action def self.action_boot Vagrant::Action::Builder.new.tap do |b| b.use CheckAccessible + b.use SetName # b.use ClearForwardedPorts b.use Provision b.use EnvSet, :port_collision_repair => true @@ -29,7 +30,7 @@ def self.action_boot b.use Customize, "pre-boot" b.use Boot b.use Customize, "post-boot" - b.use WaitForCommunicator + b.use WaitForCommunicator, [:starting, :running] b.use CheckGuestTools end end @@ -51,9 +52,9 @@ def self.action_destroy b3.use CheckAccessible b3.use EnvSet, :force_halt => true b3.use action_halt - b3.use UnregisterTemplate b3.use Destroy b3.use DestroyUnusedNetworkInterfaces + b3.use ProvisionerCleanup b3.use PrepareNFSValidIds b3.use SyncedFolderCleanup else @@ -106,9 +107,9 @@ def self.action_package #b2.use ClearForwardedPorts b2.use PrepareNFSValidIds b2.use SyncedFolderCleanup + b2.use Package b2.use Export b2.use PackageConfigFiles - b2.use Package end end end @@ -166,6 +167,7 @@ def self.action_resume b2.use CheckAccessible b2.use EnvSet, :port_collision_repair => false b2.use Resume + b2.use WaitForCommunicator, [:resuming, :running] else b2.use MessageNotCreated end @@ -236,7 +238,6 @@ def self.action_suspend b2.use MessageNotCreated end end - end end @@ -245,12 +246,21 @@ def self.action_suspend def self.action_up Vagrant::Action::Builder.new.tap do |b| b.use CheckParallels + + # Handle box_url downloading early so that if the Vagrantfile + # references any files in the box or something it all just + # works fine. + b.use Call, Created do |env, b2| + if !env[:result] + b2.use HandleBoxUrl + end + end + b.use ConfigValidate b.use Call, Created do |env, b2| # If the VM is NOT created yet, then do the setup steps if !env[:result] b2.use CheckAccessible - b2.use HandleBoxUrl b2.use RegisterTemplate b2.use Customize, "pre-import" b2.use Import @@ -291,6 +301,7 @@ def self.action_up autoload :RegisterTemplate, File.expand_path("../action/register_template", __FILE__) autoload :Resume, File.expand_path("../action/resume", __FILE__) autoload :SetupPackageFiles, File.expand_path("../action/setup_package_files", __FILE__) + autoload :SetName, File.expand_path("../action/set_name", __FILE__) autoload :Suspend, File.expand_path("../action/suspend", __FILE__) autoload :UnregisterTemplate, File.expand_path("../action/unregister_template", __FILE__) diff --git a/lib/vagrant-parallels/action/export.rb b/lib/vagrant-parallels/action/export.rb index 0dca4cf6..81f49476 100644 --- a/lib/vagrant-parallels/action/export.rb +++ b/lib/vagrant-parallels/action/export.rb @@ -1,11 +1,7 @@ -require "fileutils" - module VagrantPlugins module Parallels module Action class Export - attr_reader :temp_dir - include Util def initialize(app, env) @@ -18,33 +14,17 @@ def call(env) raise Vagrant::Errors::VMPowerOffToPackage if \ @env[:machine].provider.state.id != :stopped - setup_temp_dir export compact @app.call(env) - - recover(env) # called to cleanup temp directory - end - - def recover(env) - if temp_dir && File.exist?(temp_dir) - FileUtils.rm_rf(temp_dir) - end - end - - def setup_temp_dir - @env[:ui].info I18n.t("vagrant.actions.vm.export.create_dir") - @temp_dir = @env["export.temp_dir"] = @env[:tmp_path].join(Time.now.to_i.to_s) - FileUtils.mkpath(@env["export.temp_dir"]) end - #TODO: cleanup registered VM on interupt def export - vm_name = generate_name(@env[:root_path], '_export') + temp_vm_name = generate_name(@env[:root_path], '_export') @env[:ui].info I18n.t("vagrant.actions.vm.export.exporting") - @uuid = @env[:machine].provider.driver.export(@env["export.temp_dir"], vm_name) do |progress| + @temp_vm_uuid = @env[:machine].provider.driver.export(@env["export.temp_dir"], temp_vm_name) do |progress| @env[:ui].clear_line @env[:ui].report_progress(progress, 100, false) end @@ -56,11 +36,11 @@ def export def compact @env[:ui].info I18n.t("vagrant_parallels.actions.vm.export.compacting") - @env[:machine].provider.driver.compact(@uuid) do |progress| + @env[:machine].provider.driver.compact(@temp_vm_uuid) do |progress| @env[:ui].clear_line @env[:ui].report_progress(progress, 100, false) end - @env[:machine].provider.driver.unregister(@uuid) + @env[:machine].provider.driver.unregister(@temp_vm_uuid) # Clear the line a final time so the next data can appear # alone on the line. diff --git a/lib/vagrant-parallels/action/import.rb b/lib/vagrant-parallels/action/import.rb index 3888223f..942ae2e1 100644 --- a/lib/vagrant-parallels/action/import.rb +++ b/lib/vagrant-parallels/action/import.rb @@ -49,6 +49,9 @@ def recover(env) if env[:machine].provider.state.id != :not_created return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError) + # If we're not supposed to destroy on error then just return + return if !env[:destroy_on_error] + # Interrupted, destroy the VM. We note that we don't want to # validate the configuration here, and we don't want to confirm # we want to destroy. diff --git a/lib/vagrant-parallels/action/package.rb b/lib/vagrant-parallels/action/package.rb index 820e6d36..ad8e47c5 100644 --- a/lib/vagrant-parallels/action/package.rb +++ b/lib/vagrant-parallels/action/package.rb @@ -1,3 +1,5 @@ +require 'fileutils' + require 'vagrant/action/general/package' module VagrantPlugins @@ -8,11 +10,33 @@ class Package < Vagrant::Action::General::Package # called in the unit tests. alias_method :general_call, :call def call(env) + # Setup the temporary directory + @temp_dir = env[:tmp_path].join(Time.now.to_i.to_s) + env["export.temp_dir"] = @temp_dir + FileUtils.mkpath(env["export.temp_dir"]) + # Just match up a couple environmental variables so that # the superclass will do the right thing. Then, call the # superclass env["package.directory"] = env["export.temp_dir"] + general_call(env) + + # Always call recover to clean up the temp dir + clean_temp_dir + end + + def recover(env) + clean_temp_dir + super + end + + protected + + def clean_temp_dir + if @temp_dir && File.exist?(@temp_dir) + FileUtils.rm_rf(@temp_dir) + end end end end diff --git a/lib/vagrant-parallels/action/set_name.rb b/lib/vagrant-parallels/action/set_name.rb new file mode 100644 index 00000000..baa0a5b8 --- /dev/null +++ b/lib/vagrant-parallels/action/set_name.rb @@ -0,0 +1,53 @@ +require "log4r" + +module VagrantPlugins + module Parallels + module Action + class SetName + def initialize(app, env) + @logger = Log4r::Logger.new("vagrant::action::vm::setname") + @app = app + end + + def call(env) + name = env[:machine].provider_config.name + + # If we already set the name before, then don't do anything + sentinel = env[:machine].data_dir.join("action_set_name") + if !name && sentinel.file? + @logger.info("Default name was already set before, not doing it again.") + return @app.call(env) + end + + # If no name was manually set, then use a default + if !name + prefix = "#{env[:root_path].basename.to_s}_#{env[:machine].name}" + prefix.gsub!(/[^-a-z0-9_]/i, "") + # milliseconds + random number suffix to allow for simultaneous `vagrant up` of the same box in different dirs + name = prefix + "_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}" + end + + # Verify the name is not taken + vms_names = env[:machine].provider.driver.read_all_names + raise Vagrant::Errors::VMNameExists, :name => name if \ + vms_names.has_key?(name) && vms_names[name] != env[:machine].id + + if vms_names.has_key?(name) + @logger.info("Not setting the name because our name is already set.") + else + env[:ui].info(I18n.t( + "vagrant.actions.vm.set_name.setting_name", name: name)) + env[:machine].provider.driver.set_name(name) + end + + # Create the sentinel + sentinel.open("w") do |f| + f.write(Time.now.to_i.to_s) + end + + @app.call(env) + end + end + end + end +end diff --git a/lib/vagrant-parallels/config.rb b/lib/vagrant-parallels/config.rb index 5b8cfc77..d1ad8663 100644 --- a/lib/vagrant-parallels/config.rb +++ b/lib/vagrant-parallels/config.rb @@ -25,6 +25,15 @@ def network_adapter(slot, type, *args) @network_adapters[slot] = [type, args] end + # @param size [Integer, String] the memory size in MB + def memory=(size) + customize("pre-boot", ["set", :id, "--memsize", size.to_s]) + end + + def cpus=(count) + customize("pre-boot", ["set", :id, "--cpus", count.to_i]) + end + def finalize! if @destroy_unused_network_interfaces == UNSET_VALUE @destroy_unused_network_interfaces = true @@ -34,7 +43,7 @@ def finalize! end def validate(machine) - errors = [] + errors = _detected_errors valid_events = ["pre-import", "pre-boot", "post-boot"] @customizations.each do |event, _| if !valid_events.include?(event) diff --git a/lib/vagrant-parallels/driver/prl_ctl.rb b/lib/vagrant-parallels/driver/prl_ctl.rb index 8c98fdaf..ece2b93d 100644 --- a/lib/vagrant-parallels/driver/prl_ctl.rb +++ b/lib/vagrant-parallels/driver/prl_ctl.rb @@ -390,6 +390,10 @@ def resume execute('resume', @uuid) end + def set_name(name) + execute('set', @uuid, '--name', name, :retryable => true) + end + def set_mac_address(mac) execute('set', @uuid, '--device-set', 'net0', '--type', 'shared', '--mac', mac) end diff --git a/lib/vagrant-parallels/version.rb b/lib/vagrant-parallels/version.rb index 495fbe50..75154aae 100644 --- a/lib/vagrant-parallels/version.rb +++ b/lib/vagrant-parallels/version.rb @@ -1,5 +1,5 @@ module VagrantPlugins module Parallels - VERSION = "0.2.0" + VERSION = "0.2.1" end end diff --git a/test/unit/config_test.rb b/test/unit/config_test.rb new file mode 100644 index 00000000..8d4e7f42 --- /dev/null +++ b/test/unit/config_test.rb @@ -0,0 +1,30 @@ +require_relative "../unit/base" + +require VagrantPlugins::Parallels.source_root.join('lib/vagrant-parallels/config') + +describe VagrantPlugins::Parallels::Config do + + context "defaults" do + before { subject.finalize! } + + it "should have one Shared adapter" do + expect(subject.network_adapters).to eql({ + 0 => [:shared, []], + }) + end + end + + describe "memory=" do + it "configures memory size (in Mb)" do + subject.memory=(1024) + expect(subject.customizations).to include(["pre-boot", ["set", :id, "--memsize", '1024']]) + end + end + + describe "cpus=" do + it "configures count of cpus" do + subject.cpus=('4') + expect(subject.customizations).to include(["pre-boot", ["set", :id, "--cpus", 4]]) + end + end +end diff --git a/test/unit/driver/prl_ctl_test.rb b/test/unit/driver/prl_ctl_test.rb index 365d1f15..ec5d4067 100644 --- a/test/unit/driver/prl_ctl_test.rb +++ b/test/unit/driver/prl_ctl_test.rb @@ -83,6 +83,16 @@ end end + describe "set_name" do + it "sets new name for the VM" do + subprocess.should_receive(:execute). + with("prlctl", "set", uuid, '--name', an_instance_of(String), an_instance_of(Hash)). + and_return(subprocess_result(stdout: "Settings applied")) + + subject.set_name('new_vm_name') + end + end + describe "set_mac_address" do it "sets base MAC address to the Shared network adapter" do subprocess.should_receive(:execute).exactly(2).times. diff --git a/vagrant-parallels.gemspec b/vagrant-parallels.gemspec index 3b75581c..71326d59 100644 --- a/vagrant-parallels.gemspec +++ b/vagrant-parallels.gemspec @@ -10,13 +10,13 @@ Gem::Specification.new do |spec| spec.email = ["yshahin@gmail.com"] spec.description = %q{Enables Vagrant to manage Parallels machines.} spec.summary = %q{Enables Vagrant to manage Parallels machines.} - spec.homepage = "http://github.com/yshahin/vagrant-parallels" + spec.homepage = "http://github.com/Parallels/vagrant-parallels" spec.license = "MIT" spec.required_rubygems_version = ">= 1.3.6" spec.rubyforge_project = "vagrant-parallels" - spec.add_development_dependency "bundler", "~> 1.3" + spec.add_development_dependency "bundler", "~> 1.5.2" spec.add_development_dependency "rake" spec.add_development_dependency "rspec", "~> 2.14.0" spec.add_development_dependency "i18n-tasks", "~> 0.2.14"