The purpose of this tutorial is to show all the steps necessary to replace a VMWare fusion PRO VM from an existing Vagrant deployment.
My story is a bit strange. My VM started to increase in size a long time ago, so much that it threatened to fill all my disk space (260 Gb of VM, 500 Gb of disk, 30 Gb free remaining !).
So, each few days I had to search for big files to delete.
It worked for a long time, but the threat became too important, and finally I decided to solve the problem once and for all.
In this document, I describe in great details what took me 2 full days of painful research, trials, and mistakes.
Below are the 3 steps you will need to follow to complete the tutorial. Each step is described in great details in its own chapter.
1) Clone the VM with VMWare Fusion PRO
I’m using VMWare Fusion PRO 11.5. You will need the PRO version, to get the nice cloning features.
1) Select the VM contextual menu “Create full clone”
You will need to stop the VM first.
Do not select the “Create linked clone”, as it creates a VM which depends on the original VM that we want to get rid of.
2) Set a name for your cloned VM. Here I chose “VVV1/ default.vmwarevm”, and I first created a new folder “VV1” to store all the other files we will need for completing the process.
Here is the result of the clone operation: a new archive was created, containing all the VM files.
To check the content of the VM archive, use the contextual menu “Show package contents”:
Here is the package contents revealed:
2) Package the cloned VM in a new Vagrant Box
Why do we have to do that? Why not simply copy the VM archive?
=> Well, I tried for a few hours, and it seems that it cannot work. Basically, when you restart Vagrant with the new VM files, Vagrant simply erase them. No way to overcome that.
The standard way of installing a VM in Vagrant being a “Box”, we will create a new one from our cloned VM archive. Follow the steps below.
a) Install packer if required with this terminal command (or download it and install it manually): brew install packer
b) Create a packer.json file to give packer the instructions on how to build the Box
I followed this great tutorial https://stackoverflow.com/questions/31262833/how-to-create-a-vagrant-box-from-vmware-image-with-packer
“source_path”: “/Users/patrice/Documents/Virtual Machines.localized/VV1/VVV1: default.vmwarevm/VVV1: default.vmx”,
“shutdown_command”: “echo ‘packer’ | sudo -S shutdown -P now”
“inline”: [“echo ‘my additional provisioning steps'”]
2 instructions to modify in your own packer.json file:
- The source_path that should point to your own VM archive .vmx file
- The output that will give your Box its name
c) Launch the packing termainal command: packer build packer.json
(position yourself in your VM archive folder first, which should contain the packer.json and VM archive files)
The packing will take some time, but it worth it. Here is the content of the folder after the packing has completed:
Notice the vv1.box file, which is our desired new Box.
d) Add the new Box to the Vagrant repository
Vagrant is not yet aware of the new Box. You need to declare the Box first.
This is done with a simple terminal command: vagrant box add vv1.box –name vv1
Explanation of the command:
- “vv1.box” is your new Box file
- “- name vv1” gives your new Box its name in Vagrant’s repository
Now, let’s check that the Vagrant repository contains the new Box “vv1” with the terminal command: vagrant box list
Yes, we can see our new Box “vv1” !
3) Install the new Vagrant Box without reprovisioning
This last part is very tricky, and touchy.
We need to tell our Vagrant environment to install the new Box, but without provisioning the Box VM. We want the VM to stay as it is, because it is often the result of years of delicate tuning. So, no provisioning it is!
Below are the 6 steps process to start your Vagrant deployment with your cloned VM:
1) Be sure your Vagrant VM (the one we cloned earlier) is stopped.
If not, do it from the terminal command: vagrant halt
(position yourself in your Vagrant deployment folder first)
My Vagrant folder:
My Vagrant folder content:
2) Backup the Vagrant VM files for safety, then delete the files
Copy your whole Vagrant deployment folder somewhere safe, in case things go wrong. And for me, they did go wrong many times during my tests.
- Delete the VM from your VMWare fusion dashboard contextual menu “Delete”. Choose to delete the VM files also.
- Delete completely the “.vagrant” folder inside your Vagrant folder. It contained your current VM files (already removed from the above step), and configuration files from Vagrant.By removing the “.vagrant” folder, Vagrant will reload the new Box and install the cloned VM. This is the magical operation!
- Modify the “Vagrantfile” file
Now, we need to edit the “Vagrantfile”, to tell specific instructions to Vagrant when it loads your deployment:
- Use the new Box to install the cloned VM
- Fully clone the Box VM rather than keep a link to the Box VM
- Do not reprovision the Box, to prevent any modification of the cloned VM (we want to keep the VM as it is)
- Use ssh key user/pwd to connect to the cloned VM, and regenerate a ssh private key
Edit your vm box section as below (use your own new Box name):
config.vm.box = “vv1”
Edit your vm provider section as below (just the pink line):
config.vm.provider “vmware_fusion” do |v|
v.linked_clone = false
v.vmx[“memsize”] = “5096”
v.vmx[“numvcpus”] = “4”
v.vmx[“ethernet0.pcislotnumber”] = “33”
v.vmx[“ethernet1.pcislotnumber”] = “38”
v.vmx[“tools.upgrade.policy”] = “manual”
Comment out all provisioning instructions (except the ones marked as “always”):
config.vm.provision :shell, inline: “sudo service mysql restart”, run: “always”
config.vm.provision :shell, inline: “sudo service nginx restart”, run: “always”
# config.vm.provision :shell, :path => File.join( “provision”, “provision-pre.sh” )
# config.vm.provision :shell, :path => File.join( “provision”, “provision-custom.sh” )
# config.vm.provision :shell, :path => File.join( “provision”, “provision.sh” )
# config.vm.provision :shell, :path => File.join( “provision”, “provision-post.sh” )
Add the following section to manage the ssh key:
# When the key is lost, vagrant will shh with user/password and regenerate/install a new key
config.ssh.username = “vagrant”
1) Start vagrant with the provider “vmware_fusion”
For that, just use the terminal command: vagrant up –provider vmware_fusion
You should see the following steps indicating that the cloned VM is installed and that keys are regenerated:
Bringing machine ‘default’ up with ‘vmware_fusion’ provider…
==> default: Cloning VMware VM: ‘vv1’. This can take some time…
default: SSH address: 127.0.0.1:2200
default: SSH username: vagrant
default: SSH auth method: password
default: Inserting generated public key within guest…
default: Removing insecure key from the guest if it’s present…
default: Key inserted! Disconnecting and reconnecting using new SSH key…
2) Modify the Vagrantfile again to use the generated ssh private key
// Start the VM normally now with the SSH Key
# wpsolr: when the key is lost, vagrant will shh with user/password and regenerate/install a new key
#config.ssh.username = “vagrant”
Now, we can restart our Vagrant deployment with the cloned VM and the ssh private key: vagrant up
4) Fix an error during the first build
During my trials, I got the following error during the first Vagrant build:
# Error during the first build
An error occurred while executing `vmrun`, a utility for controlling
VMware machines. The command and output are below:
I checked the VM instances running:
Total running VMs: 3
I had to kill the 3 vms as seen below, or simply reboot!:
I suspect I deleted the .vagrant folder containing the current Vagrant VM before stopping and removing the VM from VMWare fusion.