diff --git a/README.md b/README.md index e6cd541b..7817172d 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ This provider has the following settings, all are required unless noted: * `ip_address_timeout` - _Optional_ Maximum number of seconds to wait while an IP address is obtained * `wait_for_sysprep` - _Optional_ Boolean. Enable waiting for Windows machines to reboot +* `disk_size` - _Optional_ size of vm disk in GB during the sysprep process ([#199](https://github.com/nsidc/vagrant-vsphere/pull/199)). Defaults to `false`. @@ -241,6 +242,140 @@ vsphere.mac = '00:50:56:XX:YY:ZZ' Take care to avoid using invalid or duplicate VMware MAC addresses, as this can easily break networking. +### Setting disk size + +To set a specific disk size (in GB) add `disk_size` to your `Vagrantfile`: +```ruby +vsphere.disk_size = 25 +``` + +This option calls disk resizing task right after `vagrant up`. +It changes only disk size, you have to care youself about partitioning, volumes and filesystem using provisioning script. + +#### Example #### + +Let's asume we have Ubuntu Xenial installed on a 16G disk in 'LVM, entire disk' mode, here is initial disk state: + + +`fdisk -l`: + +```shell +Disk /dev/sda: 16 GiB, 17179869184 bytes, 33554432 sectors +... + +Device Boot Start End Sectors Size Id Type +/dev/sda1 * 2048 1499135 1497088 731M 83 Linux +/dev/sda2 1501182 33552383 32051202 15.3G 5 Extended +/dev/sda5 1501184 33552383 32051200 15.3G 8e Linux LVM + +... +``` + +`pvs`: +```shell + PV VG Fmt Attr PSize PFree + /dev/sda5 ubuntu-vg lvm2 a-- 15.28g 12.00m +``` + +`vgs`: +```shell + VG #PV #LV #SN Attr VSize VFree + ubuntu-vg 1 2 0 wz--n- 15.28g 12.00m +``` + +`lvs`: +```shell + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + root ubuntu-vg -wi-ao---- 14.32g + + swap_1 ubuntu-vg -wi-ao---- 976.00m +``` + +`df -h`: +```shell +... +/dev/mapper/ubuntu--vg-root 14G 1.5G 12G 11% / +... +``` + +To change disk size to 25G and apply partitioning, lvm and filesystem parameters add following code to `Vagrantfile`: + +```ruby +... +$script = <<-SCRIPT +apt update -y \ + && apt install -y parted \ + && parted /dev/sda resizepart 2 100% \ + && parted /dev/sda resizepart 5 100% \ + && pvresize /dev/sda5 \ + && lvextend -l100%VG /dev/ubuntu-vg/root \ + && resize2fs /dev/ubuntu-vg/root +SCRIPT + +Vagrant.configure(2) do |config| + ... + config.vm.box_check_update = true + config.vm.provider :vsphere do |vsphere| + ... + vsphere.disk_size = 25 + ... + end + config.vm.provision "shell", inline: $script + ... +end +... + +``` + +After `vagrant up` altered disk state is: + +`fdisk -l`: + +```shell +Disk /dev/sda: 25 GiB, 26843545600 bytes, 52428800 sectors +... + +Device Boot Start End Sectors Size Id Type +/dev/sda1 * 2048 1499135 1497088 731M 83 Linux +/dev/sda2 1501182 52428799 50927618 24.3G 5 Extended +/dev/sda5 1501184 52428799 50927616 24.3G 8e Linux LVM + + +Disk /dev/mapper/ubuntu--vg-root: 23.3 GiB, 25048383488 bytes, 48922624 sectors +... + + +Disk /dev/mapper/ubuntu--vg-swap_1: 976 MiB, 1023410176 bytes, 1998848 sectors +... +``` + +`pvs`: +```shell + PV VG Fmt Attr PSize PFree + /dev/sda5 ubuntu-vg lvm2 a-- 24.28g 0 +``` + +`vgs`: +```shell + VG #PV #LV #SN Attr VSize VFree + ubuntu-vg 1 2 0 wz--n- 24.28g 0 +``` + +`lvs`: +```shell + LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert + root ubuntu-vg -wi-ao---- 23.33g + + swap_1 ubuntu-vg -wi-ao---- 976.00m +``` + +`df -h`: +```shell +... +/dev/mapper/ubuntu--vg-root 23G 1.5G 21G 7% / +... +``` + ## Troubleshooting ### vCenter diff --git a/lib/vSphere/action/clone.rb b/lib/vSphere/action/clone.rb index 00116cf6..e2ecc142 100644 --- a/lib/vSphere/action/clone.rb +++ b/lib/vSphere/action/clone.rb @@ -19,6 +19,7 @@ def call(env) name = get_name machine, config, env[:root_path] dc = get_datacenter connection, machine template = dc.find_vm config.template_name + disk_size_in_gb = config.disk_size.to_i fail Errors::VSphereError, :'missing_template' if template.nil? vm_base_folder = get_vm_base_folder dc, template, config fail Errors::VSphereError, :'invalid_base_path' if vm_base_folder.nil? @@ -29,7 +30,7 @@ def call(env) fail Errors::VSphereError, :'invalid_configuration_linked_clone_with_sdrs' if config.linked_clone && ds.is_a?(RbVmomi::VIM::StoragePod) location = get_location ds, dc, machine, template - spec = RbVmomi::VIM.VirtualMachineCloneSpec location: location, powerOn: true, template: false + spec = RbVmomi::VIM.VirtualMachineCloneSpec location: location, powerOn: false, template: false spec[:config] = RbVmomi::VIM.VirtualMachineConfigSpec customization_info = get_customization_spec_info_by_name connection, machine @@ -58,6 +59,8 @@ def call(env) add_custom_extra_config(spec, config.extra_config) unless config.extra_config.empty? add_custom_notes(spec, config.notes) unless config.notes.nil? + env[:ui].info "Setting custom disk size: #{disk_size_in_gb}" if disk_size_in_gb.to_i > 0 + if !config.clone_from_vm && ds.is_a?(RbVmomi::VIM::StoragePod) storage_mgr = connection.serviceContent.storageResourceManager @@ -90,6 +93,8 @@ def call(env) env[:ui].info " -- Target VM: #{vm_base_folder.pretty_path}/#{name}" new_vm = template.CloneVM_Task(folder: vm_base_folder, name: name, spec: spec).wait_for_completion + resize_disk(new_vm, disk_size_in_gb) if disk_size_in_gb.to_i > 0 + new_vm.PowerOnVM_Task.wait_for_completion config.custom_attributes.each do |k, v| env[:ui].info "Setting custom attribute: #{k}=#{v}" @@ -146,6 +151,23 @@ def query_customization_succeeded(vm, vem) RbVmomi::VIM::EventFilterSpecRecursionOption(:self)), eventTypeId: ['CustomizationSucceeded'])) end + def resize_disk(machine, size) + # get current vm disk + virtual_disk = machine.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)[0] + virtual_disk.capacityInKB = size * 1024 * 1024 + + # execute reconfigure task + new_vm_spec = RbVmomi::VIM.VirtualMachineConfigSpec( + :deviceChange => [RbVmomi::VIM.VirtualDeviceConfigSpec( + :device => virtual_disk, + :operation => RbVmomi::VIM.VirtualDeviceConfigSpecOperation(:edit) + )] + ) + task = machine.ReconfigVM_Task(:spec => new_vm_spec) + task.wait_for_completion + { 'task_state' => task.info.state } + end + def get_customization_spec(machine, spec_info) customization_spec = spec_info.spec.clone diff --git a/lib/vSphere/config.rb b/lib/vSphere/config.rb index 19d3efb5..76dcce6a 100644 --- a/lib/vSphere/config.rb +++ b/lib/vSphere/config.rb @@ -31,6 +31,7 @@ class Config < Vagrant.plugin('2', :config) attr_accessor :real_nic_ip attr_accessor :notes attr_accessor :wait_for_sysprep + attr_accessor :disk_size attr_reader :custom_attributes