如果已经配置了Vagrant VM,请避免重新配置

时间:2013-01-10 19:31:47

标签: vagrant

我正在尝试使用shell配置程序,以避免重新配置虚拟机实例(如果之前已经这样做过)。

考虑以下Vagrantfile:

Vagrant::Config.run do |config|
  config.vm.define :minimal do |config|
    # Base image
    config.vm.box = "lucid32"
    config.vm.box_url = "http://files.vagrantup.com/lucid32.box"

    config.vm.provision :shell, :inline => "mkdir /tmp/foobar"
  end
end

如果您运行vagrant up minimal,它将创建该框并最初进行配置。如果然后运行vagrant provision minimal,它将尝试重新配置该框但会失败(因为/ tmp / foobar目录已经存在)。

有没有办法让Vagrant记住它过去是否配置了一台机器并避免以后重置它?

更多上下文:如果我运行vagrant up minimal,重新启动我的主机,然后再次运行vagrant up minimal,它将尝试重新配置该框并失败。这种情况经常发生,因为VirtualBox经常在我的主机上引起内核恐慌。

5 个答案:

答案 0 :(得分:10)

这可能不是您想要的答案,但如果您将mkdir更改为mkdir -p,则可以使用;)

但是,严肃地说,我认为Vagrant希望供应商是幂等的(也就是说,如果第二次运行,它将不采取任何行动)。

实现真正的幂等性可能很棘手,具体取决于您在配置脚本中实际执行的操作,但mkdir -p是一个良好的开端。您还可以在系统上创建一个标志文件,并首先检查该标志文件是否存在;如果存在,只需exit 0

答案 1 :(得分:6)

如果你正在使用bash配置脚本,那么它的可能性就不会是幂等的。

这是一个如何避免配置两次的低级示例:

PROVISIONED="/some-app-dir/PROVISIONED";

if [[ -f $PROVISIONED ]]; then
  echo "Skipping provisioning";
  exit;
else
  echo "Provisioning";
fi

#...do provisioning things

touch $PROVISIONED;

答案 2 :(得分:5)

你看过这个吗?

vagrant up --no-provision

$ vagrant up --help
Usage: vagrant up [vm-name] [options] [-h]

    --[no-]provision             Enable or disable provisioning
    --provision-with x,y,z       Enable only certain provisioners, by type.
    --[no-]parallel              Enable or disable parallelism if provider supports it.
    --provider provider          Back the machine with a specific provider.
-h, --help                       Print this help

答案 3 :(得分:4)

Vagrant通常只在第一个 vagrant up 上运行配置代码,当您明确告知它时,例如使用vagrant provisionvagrant reload --provision。实际上没有必要尽量避免再次运行配置脚本。 (这may not have been the case when you posted the question, however。)

如果您正在使用Chef或Puppet进行配置,那么它们已经被设计为制作所有内容idempotent,并且我认为Salt和Ansible也是如此。

如果您正在使用shell脚本并且希望使它们具有幂等性,则可以在if语句中检查某些条件(如文件的存在):

if [[! -f "$HOME/bin/something.sh" ]]; then
  # install something.sh into ~/bin
fi

我已经给出了一个非常一般的答案,因为我假设mkdir /tmp/foobar不是真的你想要实现的目标,但如果是,那么添加{ {1}}。

答案 4 :(得分:-1)

我无法重现错误。一旦盒子启动,它就不应该提供,除非你使用设施明确地实现它。

更重要的是,正如许多其他人所指出的那样,配置应始终为idempotent

  

Idempotence 配方可以在同一系统上多次运行,结果将始终相同。资源在a中定义   配方,然后定义要在系统上执行的操作。   厨师 - 客户确保如果不执行操作   资源没有改变,任何执行的动作都是   每次都以同样的方式完成。如果重新运行配方而没有任何配方   改变了,然后厨师 - 客户不会做任何事情。

参考:https://docs.getchef.com/chef_why.html#idempotence