Class: Kitchen::Driver::Hyperv

Inherits:
Base
  • Object
show all
Includes:
PowerShellScripts
Defined in:
lib/kitchen/driver/hyperv.rb

Overview

Test Kitchen driver that builds instances as Hyper-V virtual machines.

The driver never talks to Hyper-V directly. It generates PowerShell that calls the helper functions in support/hyperv.ps1 and runs that script through a Train connection -- a local one on a Hyper-V host, or WinRM when hyperv_server points at a remote host.

Each instance gets a differencing disk cloned from a shared parent VHD, so creating an instance costs a few seconds and very little disk.

Examples:

Minimal kitchen.yml

driver:
  name: hyperv
  parent_vhd_folder: C:\VHDs
  parent_vhd_name: windows-2022.vhdx

See Also:

Constant Summary

Constants included from PowerShellScripts

PowerShellScripts::SIXTY_FOUR_BIT_ARCHITECTURES

Instance Method Summary collapse

Methods included from PowerShellScripts

#additional_disks, #copy_vm_file_ps, #delete_vm_ps, #encode_command, #ensure_vm_running_ps, #execute_command, #hyperv_module_ps, #is_32bit?, #is_64bit?, #mount_vm_iso, #new_additional_disk_ps, #new_differencing_disk_ps, #new_vm_ps, #os_architecture, #powershell_64_bit, #resize_vhd, #ruby_architecture_bits, #run_ps, #sanitize_stdout, #set_vm_ipaddress_ps, #set_vm_note, #sixty_four_bit?, #thirty_two_bit?, #vm_default_switch_ps, #vm_details_ps, #vm_status_ps, #wrap_command

Instance Method Details

#create(state) ⇒ void

This method returns an undefined value.

Create the virtual machine and wait until it is reachable.

Runs the full bring-up in order: validate the configuration, clone the parent VHD into a differencing disk, create any additional data disks, create and start the VM, then block on the transport until the guest accepts connections.

Parameters:

  • state (Hash)

    the instance state hash, updated in place with :id, :hostname and :vm_name

Raises:

  • (RuntimeError)

    if validation fails or Hyper-V cannot create the VM



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/kitchen/driver/hyperv.rb', line 108

def create(state)
  @state = state
  # Kitchen::Driver::Base#create runs config[:pre_create_command].
  # Without this the option is silently ignored.
  super
  validate_vm_settings
  create_new_differencing_disk
  create_additional_disks
  create_virtual_machine
  set_virtual_machine_note
  update_state
  mount_virtual_machine_iso
  instance.transport.connection(@state).wait_until_ready
  copy_vm_files
  info("Hyper-V instance #{instance.to_str} created.")
end

#destroy(state) ⇒ void

This method returns an undefined value.

Destroy the virtual machine and the disks created alongside it.

Safe to call repeatedly and safe to call when the VM was removed out of band: a differencing disk left behind by a partial create is cleaned up even when no VM exists.

Parameters:

  • state (Hash)

    the instance state hash; :id is deleted from it



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/kitchen/driver/hyperv.rb', line 133

def destroy(state)
  @state = state
  if differencing_disk_exists && !vm_exists_silent
    remove_differencing_disk
  end
  unless vm_exists
    # The VM is gone, but a stale id would make every later run believe
    # otherwise, so clear it rather than returning with it still in place.
    state.delete(:id)
    return
  end

  instance.transport.connection(state).close
  remove_virtual_machine
  remove_differencing_disk
  remove_additional_disks
  info("The Hyper-V instance #{instance.to_str} has been removed.")
  state.delete(:id)
end

#doctor(state) ⇒ Boolean

Check for the common reasons this driver cannot build an instance.

Backs kitchen doctor. Reports every problem it finds rather than stopping at the first, since they are usually related.

Parameters:

  • state (Hash)

    the instance state hash

Returns:

  • (Boolean)

    true if at least one problem was found



191
192
193
194
195
196
# File 'lib/kitchen/driver/hyperv.rb', line 191

def doctor(state)
  @state = state
  problems = hyperv_problems + parent_vhd_problems
  problems.each { |problem| warn(problem) }
  !problems.empty?
end

#status(state) ⇒ Hash

Report whether Hyper-V still has this instance's virtual machine.

Backs kitchen list --probe. Deliberately read-only: unlike the check #create makes, this never starts a stopped VM.

Parameters:

  • state (Hash)

    the instance state hash

Returns:

  • (Hash)

    normalized status data for Test Kitchen



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/kitchen/driver/hyperv.rb', line 160

def status(state)
  @state = state
  if state[:id].nil?
    return status_report(
      live: false,
      state: "not_created",
      message: "No virtual machine id recorded for this instance."
    )
  end

  vm = run_ps vm_status_ps
  if vm.nil? || vm["Id"].nil?
    status_report(live: false, state: "not_created", resource_id: state[:id],
      message: "Hyper-V has no virtual machine with id #{state[:id]}.")
  else
    running = vm["State"].to_s.casecmp?("running")
    status_report(live: running, state: running ? "running" : "stopped",
      resource_id: vm["Id"],
      message: "Hyper-V reports the virtual machine as #{vm["State"]}.")
  end
rescue => e
  status_report(live: nil, state: "unknown", resource_id: state[:id], message: e.message)
end