Vagrant在销毁之前分离.vdi文件或只是不删除它

时间:2017-07-11 15:04:47

标签: vagrant

在Vagrantfile中,我附加手动创建的db.vdi磁盘:

vb.customize [
  'storageattach', :id, 
  '--storagectl', 'SATA Controller', 
  '--port', 1, '--device', 0, 
  '--type', 'hdd', 
  '--medium', 'db.vdi'
]

它工作得很好,但是当我销毁流浪者盒子时,这个文件被删除了。我试图修复那个修复流浪者的触发器。 before :destroy before :halt不起作用,我收到驱动器不可热插拔的错误。 after :halt根本不起作用:

config.trigger.after :halt do
  run "VBoxManage storageattach '#{@machine.id}'" +
    " --storagectl 'SATA Controller' --port 1 --device 0 --type hdd --medium none"
end

我想要做的是,当我运行vagrant destroy时,我想优雅地停止机器,取消附加vdi文件,这样流浪者不会删除它,摧毁其他所有内容。

有可能吗?

编辑:

看起来可以使用插件挂钩https://github.com/kusnier/vagrant-persistent-storage/blob/master/lib/vagrant-persistent-storage/plugin.rb - 看看对Action.detach_storage的引用,但我不知道如何在Vagrantfile中使用它

请参阅@FrédéricHenri - 分离很快就会触发:

==> default: Running triggers before destroy...
==> default: dettach drive
==> !!! TOO SOON !!!
==> default: Executing command "VBoxManage storageattach d0132b78-11ea-41cf-b003-dac15536520c --storagectl SATAController --port 1 --device 0 --type hdd --medium none"...
==> default: Command execution finished.
    default: Are you sure you want to destroy the 'default' VM? [y/N] y

==> default: Forcing shutdown of VM...
==> !!! THIS IS WHERE I SHOULD DETACH THE DRIVE !!!
==> default: Destroying VM and associated drives...

3 个答案:

答案 0 :(得分:1)

我找到了这个插件https://github.com/kusnier/vagrant-persistent-storage

它看起来像我需要但不幸的是只有一个磁盘选项

答案 1 :(得分:1)

我认为你是正确的,就好像你看一下示例插件一样,它们在halt命令之后和destroy之前挂钩。

获取机器ID

问题在于您运行命令的方式run "VBoxManage storageattach '#{@machine.id}'" ..将返回空machine.id; Vagrantfile脚本中的vagrant不知道它正在构建的计算机,因此您会收到一条错误,指出它找不到具有空ID /名称的引用VM,并且该命令无法成功执行。

您需要的是获取VirtualBox VM Id,以便将其传递给命令;此ID保存在文件.vagrant/machines/<name>/<provider>/id中,假设您没有为VM设置特定名称,它将是:

在销毁触发器

之前使用
  config.trigger.before :destroy do
    info "dettach drive"
    machineId = File.read(".vagrant/machines/default/virtualbox/id")
    run "VBoxManage storageattach '#{machineId}'" +
      " --storagectl 'SATA Controller' --port 1 --device 0 --type hdd --medium none"
  end
在销毁VM时弹出驱动器时出现

hotpluggable错误

对于 hotpluggable pat,您需要确保文件在连接时确实是可热插拔的,以便在VM仍在运行时(即在销毁之前)拔出它

您可以在连接硬盘时从Vagrantfile进行此配置

vb.customize [
  'storageattach', :id, 
  '--storagectl', 'SATAController', 
  '--port', 1, '--device', 0, 
  '--type', 'hdd', 
  '--medium', 'db.vdi',
  '--hotpluggable', 'on'
]

为此VM运行destroy命令时,您将获得

fhenri:~/project/vagrant/drive$ vagrant destroy
==> default: Running triggers before destroy...
==> default: dettach drive
==> default: Executing command "VBoxManage storageattach d0132b78-11ea-41cf-b003-dac15536520c --storagectl SATAController --port 1 --device 0 --type hdd --medium none"...
==> default: Command execution finished.
    default: Are you sure you want to destroy the 'default' VM? [y/N] y

==> default: Forcing shutdown of VM...
==> default: Destroying VM and associated drives...

所以你可以清楚地看到命令被正确执行并且驱动器被取消了,我可以看到驱动器仍然在我的本地硬盘上,然后我可以回答是以销毁VM文件

在暂停触发器

后使用

就我而言,它也可以在停止触发器挂钩后与一样好用:

来自Vagrantfile的

  config.trigger.after :halt do
    info "dettach drive"
    machineId = File.read(".vagrant/machines/default/virtualbox/id")
    run "VBoxManage storageattach '#{machineId}'" +
      " --storagectl 'SATAController' --port 1 --device 0 --type hdd --medium none"
  end

将运行

fhenri:~/project/vagrant/drive$ vagrant halt
==> default: Attempting graceful shutdown of VM...
==> default: Running triggers after halt...
==> default: dettach drive
==> default: Executing command "VBoxManage storageattach 74274ab6-173e-4934-9864-33e09be26214 --storagectl SATAController --port 1 --device 0 --type hdd --medium none"...
==> default: Command execution finished.

剩下的问题是确保在这种情况下不要调用 destroy ,因为destroy不会停止VM,它只是销毁它所以它不会调用halt命令并绕过停止触发器,你可以使用额外的detroy插件,但它将意味着你不想要的热插拔的东西

如果连接了驱动器,则防止销毁

您可以查看vboxmanage showvminfo <uuid>并查看 storagecontrollerportcount0

的值,查看设备上附带的驱动器数量

你可以在之前的销毁触发器中翻译它

  config.trigger.before :destroy do
    vm_info = `vboxmanage showvminfo #{@machine.id} --machinereadable | grep storagecontrollerportcount0`
    value = Integer(vm_info.split("=")[1].gsub('"','').chomp())
    raise Vagrant::Errors::VagrantError.new, "drive attached - cannot be destroyed" if value > 1
  end

如果连接了多个驱动器并且不会继续执行destroy命令

,则会引发错误

答案 2 :(得分:0)

我已经在Windows7主机上,带有fedora guest(奇怪的是有一个IDE控制器)的流浪汉2.1.1(2.1.2触发中断)上对其进行了测试。

因此,我的解决方案可能是愚蠢的,如下所示:

Thread.sleep(1000)

因此,基本上,当您在“ before”之前调用trigger destroy时,它首先停止机器(“ halt”之后为触发器),分离磁盘,然后调用destroy。它既可以在运行的计算机上运行,​​也可以在停止的计算机上运行。这样的永久磁盘。

P.S。它可能需要一些保护措施