class VagrantPlugins::ProviderLibvirt::Config

Attributes

autostart[RW]

Autostart

boot_order[RW]
cdroms[RW]
channel[RW]
channels[RW]

Channels

clock_offset[RW]
clock_timers[RW]
cmd_line[RW]
connect_via_ssh[RW]

If use ssh tunnel to connect to Libvirt.

cpu_fallback[RW]
cpu_features[RW]
cpu_mode[RW]
cpu_model[RW]
cpu_topology[RW]
cpus[RW]
cpuset[RW]
default_prefix[RW]

Default host prefix (alternative to use project folder name)

description[RW]
disk_bus[RW]
disk_controller_model[RW]
disk_device[RW]
disk_driver_opts[RW]
disks[RW]

Storage

driver[RW]

A hypervisor name to access via Libvirt.

dtb[RW]
emulator_path[RW]
features[RW]
features_hyperv[RW]
forward_ssh_port[RW]

Forward port with id 'ssh'

graphics_autoport[RW]
graphics_gl[RW]
graphics_ip[RW]
graphics_passwd[RW]
graphics_port[RW]
graphics_type[RW]
host[RW]

The name of the server, where Libvirtd is running.

host_device_exclude_prefixes[RW]

internal helper attributes

id_ssh_key_file[RW]

ID SSH key file

initrd[RW]
inputs[RW]

Inputs

kernel[RW]
keymap[RW]
kvm_hidden[RW]
loader[RW]
machine_arch[RW]
machine_type[RW]
machine_virtual_size[RW]
management_network_address[RW]
management_network_autostart[RW]
management_network_device[RW]

Libvirt default network

management_network_domain[RW]
management_network_guest_ipv6[RW]
management_network_keep[RW]
management_network_mac[RW]
management_network_mode[RW]
management_network_mtu[RW]
management_network_name[RW]
management_network_pci_bus[RW]
management_network_pci_slot[RW]
memballoon_enabled[RW]

Configure the memballoon

memballoon_model[RW]
memballoon_pci_bus[RW]
memballoon_pci_slot[RW]
memory[RW]
memory_backing[RW]
mgmt_attach[RW]

Attach mgmt network

nested[RW]
nic_adapter_count[RW]

Sets the max number of NICs that can be created Default set to 8. Don't change the default unless you know what are doing

nic_model_type[RW]
nodeset[RW]
numa_nodes[RW]
nvram[RW]
password[RW]

Password for Libvirt connection.

pcis[RW]

PCI device passthrough

proxy_command[RW]
qemu_args[RW]

Additional qemuargs arguments

qemu_env[RW]

Additional qemuenv arguments

qemu_use_agent[RW]

Use QEMU Agent to get ip address

qemu_use_session[RW]

Use QEMU session instead of system

random_hostname[RW]

Turn on to prevent hostname conflicts

redirdevs[RW]

Redirected devices

redirfilters[RW]
rng[RW]

Random number device passthrough

serials[RW]

serial consoles

shares[RW]
smartcard_dev[RW]

smartcard device

snapshot_pool_name[RW]

Libvirt storage pool where the base image snapshot shall be stored

socket[RW]

Path towards the Libvirt socket

sound_type[RW]
storage_pool_name[RW]

Libvirt storage pool name, where box image and instance snapshots will be stored.

storage_pool_path[RW]
suspend_mode[RW]

Suspend mode

sysinfo[RW]

Configure sysinfo values

system_uri[RW]

System connection information

title[RW]

Domain specific settings used while creating new domain.

tpm_model[RW]

Sets the information for connecting to a host TPM device Only supports socket-based TPMs

tpm_path[RW]
tpm_type[RW]
tpm_version[RW]
uri[RW]

will supersede most other options if provided

usbctl_dev[RW]

USB controller

usbs[RW]

USB device passthrough

username[RW]

The username to access Libvirt.

uuid[RW]
video_accel3d[RW]
video_type[RW]
video_vram[RW]
volume_cache[RW]
watchdog_dev[RW]

Watchdog device

Public Class Methods

new() click to toggle source
# File lib/vagrant-libvirt/config.rb, line 204
def initialize
  @uri               = UNSET_VALUE
  @driver            = UNSET_VALUE
  @host              = UNSET_VALUE
  @port              = UNSET_VALUE
  @connect_via_ssh   = UNSET_VALUE
  @username          = UNSET_VALUE
  @password          = UNSET_VALUE
  @id_ssh_key_file   = UNSET_VALUE
  @socket            = UNSET_VALUE
  @proxy_command     = UNSET_VALUE
  @forward_ssh_port  = UNSET_VALUE # forward port with id 'ssh'
  @storage_pool_name = UNSET_VALUE
  @snapshot_pool_name = UNSET_VALUE
  @random_hostname   = UNSET_VALUE
  @management_network_device  = UNSET_VALUE
  @management_network_name    = UNSET_VALUE
  @management_network_address = UNSET_VALUE
  @management_network_mode = UNSET_VALUE
  @management_network_mac  = UNSET_VALUE
  @management_network_guest_ipv6 = UNSET_VALUE
  @management_network_autostart = UNSET_VALUE
  @management_network_pci_slot = UNSET_VALUE
  @management_network_pci_bus = UNSET_VALUE
  @management_network_domain = UNSET_VALUE
  @management_network_mtu = UNSET_VALUE
  @management_network_keep = UNSET_VALUE

  # System connection information
  @system_uri      = UNSET_VALUE

  # Domain specific settings.
  @title             = UNSET_VALUE
  @description       = UNSET_VALUE
  @uuid              = UNSET_VALUE
  @memory            = UNSET_VALUE
  @nodeset           = UNSET_VALUE
  @memory_backing    = UNSET_VALUE
  @cpus              = UNSET_VALUE
  @cpuset            = UNSET_VALUE
  @cpu_mode          = UNSET_VALUE
  @cpu_model         = UNSET_VALUE
  @cpu_fallback      = UNSET_VALUE
  @cpu_features      = UNSET_VALUE
  @cpu_topology      = UNSET_VALUE
  @shares            = UNSET_VALUE
  @features          = UNSET_VALUE
  @features_hyperv   = UNSET_VALUE
  @clock_offset      = UNSET_VALUE
  @clock_timers      = []
  @numa_nodes        = UNSET_VALUE
  @loader            = UNSET_VALUE
  @nvram             = UNSET_VALUE
  @machine_type      = UNSET_VALUE
  @machine_arch      = UNSET_VALUE
  @machine_virtual_size = UNSET_VALUE
  @disk_bus          = UNSET_VALUE
  @disk_device       = UNSET_VALUE
  @disk_controller_model = UNSET_VALUE
  @disk_driver_opts  = {}
  @nic_model_type    = UNSET_VALUE
  @nested            = UNSET_VALUE
  @volume_cache      = UNSET_VALUE
  @kernel            = UNSET_VALUE
  @initrd            = UNSET_VALUE
  @dtb               = UNSET_VALUE
  @cmd_line          = UNSET_VALUE
  @emulator_path     = UNSET_VALUE
  @graphics_type     = UNSET_VALUE
  @graphics_autoport = UNSET_VALUE
  @graphics_port     = UNSET_VALUE
  @graphics_ip       = UNSET_VALUE
  @graphics_passwd   = UNSET_VALUE
  @graphics_gl       = UNSET_VALUE
  @video_type        = UNSET_VALUE
  @video_vram        = UNSET_VALUE
  @video_accel3d     = UNSET_VALUE
  @sound_type        = UNSET_VALUE
  @keymap            = UNSET_VALUE
  @kvm_hidden        = UNSET_VALUE

  @tpm_model         = UNSET_VALUE
  @tpm_type          = UNSET_VALUE
  @tpm_path          = UNSET_VALUE
  @tpm_version       = UNSET_VALUE

  @sysinfo           = UNSET_VALUE

  @memballoon_enabled = UNSET_VALUE
  @memballoon_model   = UNSET_VALUE
  @memballoon_pci_bus = UNSET_VALUE
  @memballoon_pci_slot = UNSET_VALUE

  @nic_adapter_count = UNSET_VALUE

  # Boot order
  @boot_order        = []
  # Storage
  @disks             = []
  @cdroms            = []

  # Inputs
  @inputs            = UNSET_VALUE

  # Channels
  @channels          = UNSET_VALUE

  # PCI device passthrough
  @pcis              = UNSET_VALUE

  # Random number device passthrough
  @rng = UNSET_VALUE

  # Watchdog device
  @watchdog_dev      = UNSET_VALUE

  # USB controller
  @usbctl_dev        = UNSET_VALUE

  # USB device passthrough
  @usbs              = UNSET_VALUE

  # Redirected devices
  @redirdevs         = UNSET_VALUE
  @redirfilters      = UNSET_VALUE

  # smartcard device
  @smartcard_dev     = UNSET_VALUE

  # Suspend mode
  @suspend_mode      = UNSET_VALUE

  # Autostart
  @autostart         = UNSET_VALUE

  # Attach mgmt network
  @mgmt_attach       = UNSET_VALUE

  # Additional QEMU commandline arguments
  @qemu_args         = UNSET_VALUE

  # Additional QEMU commandline environment variables
  @qemu_env          = UNSET_VALUE

  @qemu_use_session  = UNSET_VALUE

  # Use Qemu agent to get ip address
  @qemu_use_agent  = UNSET_VALUE

  @serials           = UNSET_VALUE

  # internal options to help override behaviour
  @host_device_exclude_prefixes = UNSET_VALUE
end

Public Instance Methods

_default_uri() click to toggle source
# File lib/vagrant-libvirt/config.rb, line 735
def _default_uri
  # Determine if any settings except driver provided explicitly, if not
  # and the LIBVIRT_DEFAULT_URI var is set, use that.
  #
  # Skipping driver because that may be set on individual boxes rather
  # than by the user.
  if [
      @connect_via_ssh, @host, @username, @password,
      @id_ssh_key_file, @qemu_use_session, @socket,
  ].none?{ |v| v != UNSET_VALUE }
    if ENV.fetch('LIBVIRT_DEFAULT_URI', '') != ""
      @uri = ENV['LIBVIRT_DEFAULT_URI']
    end
  end
end
_generate_numa() click to toggle source
# File lib/vagrant-libvirt/config.rb, line 381
def _generate_numa
  @numa_nodes.collect { |x|
    # Perform some validation of cpu values
    unless x[:cpus] =~ /^\d+-\d+$/
      raise 'numa_nodes[:cpus] must be in format "integer-integer"'
    end

    # Convert to KiB
    x[:memory] = x[:memory].to_i * 1024
  }

  # Grab the value of the last @numa_nodes[:cpus] and verify @cpus matches
  # Note: [:cpus] is zero based and @cpus is not, so we need to +1
  last_cpu = @numa_nodes.last[:cpus]
  last_cpu = last_cpu.scan(/\d+$/)[0]
  last_cpu = last_cpu.to_i + 1

  if @cpus != last_cpu.to_i
    raise 'The total number of numa_nodes[:cpus] must equal config.cpus'
  end

  @numa_nodes
end
_generate_uri(qemu_use_session) click to toggle source

code to generate URI from from either the LIBVIRT_URI environment variable or a config moved out of the connect action

# File lib/vagrant-libvirt/config.rb, line 753
def _generate_uri(qemu_use_session)
  # builds the Libvirt connection URI from the given driver config
  # Setup connection uri.
  uri = @driver.dup
  virt_path = case uri
              when 'qemu', 'kvm'
                qemu_use_session ? '/session' : '/system'
              when 'openvz', 'uml', 'phyp', 'parallels'
                '/system'
              when '@en', 'esx'
                '/'
              when 'vbox', 'vmwarews', 'hyperv'
                '/session'
              else
                raise "Require specify driver #{uri}"
  end
  if uri == 'kvm'
    uri = 'qemu' # use QEMU uri for KVM domain type
  end

  # turn on ssh if an ssh key file is explicitly provided
  if @connect_via_ssh == UNSET_VALUE && @id_ssh_key_file && @id_ssh_key_file != UNSET_VALUE
    @connect_via_ssh = true
  end

  params = {}

  if @connect_via_ssh == true
    finalize_id_ssh_key_file

    uri += '+ssh://'
    uri += "#{@username}@" if @username && @username != UNSET_VALUE

    uri += (@host && @host != UNSET_VALUE ? @host : 'localhost')

    params['no_verify'] = '1'
    params['keyfile'] = @id_ssh_key_file if @id_ssh_key_file
  else
    uri += '://'
    uri += @host if @host && @host != UNSET_VALUE
  end

  uri += virt_path

  # set path to Libvirt socket
  params['socket'] = @socket if @socket

  uri += '?' + params.map { |pair| pair.join('=') }.join('&') unless params.empty?
  uri
end
_get_cdrom_dev(cdroms) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 363
def _get_cdrom_dev(cdroms)
  exist = Hash[cdroms.collect { |x| [x[:dev], true] }]
  # hda - hdc
  curr = 'a'.ord
  while curr <= 'd'.ord
    dev = "hd#{curr.chr}"
    if exist[dev]
      curr += 1
      next
    else
      return dev
    end
  end

  # is it better to raise our own error, or let Libvirt cause the exception?
  raise 'Only four cdroms may be attached at a time'
end
_handle_cdrom_storage(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 651
def _handle_cdrom_storage(options = {})
  # <disk type="file" device="cdrom">
  #   <source file="/home/user/virtio-win-0.1-100.iso"/>
  #   <target dev="hdc"/>
  #   <readonly/>
  #   <address type='drive' controller='0' bus='1' target='0' unit='0'/>
  # </disk>
  #
  # note the target dev will need to be changed with each cdrom drive (hdc, hdd, etc),
  # as will the address unit number (unit=0, unit=1, etc)

  options = {
    type: 'raw',
    bus: 'ide',
    path: nil
  }.merge(options)

  cdrom = {
    type: options[:type],
    dev: options[:dev],
    bus: options[:bus],
    path: options[:path]
  }

  @cdroms << cdrom
end
_handle_disk_storage(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 678
def _handle_disk_storage(options = {})
  options = {
    type: 'qcow2',
    size: '10G', # matches the fog default
    path: nil,
    bus: 'virtio'
  }.merge(options)

  disk = {
    device: options[:device],
    type: options[:type],
    size: options[:size],
    path: options[:path],
    bus: options[:bus],
    cache: options[:cache] || 'default',
    allow_existing: options[:allow_existing],
    shareable: options[:shareable],
    serial: options[:serial],
    io: options[:io],
    copy_on_read: options[:copy_on_read],
    discard: options[:discard],
    detect_zeroes: options[:detect_zeroes],
    pool: options[:pool], # overrides storage_pool setting for additional disks
    wwn: options[:wwn],
  }

  @disks << disk # append
end
_parse_uri(uri) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 804
def _parse_uri(uri)
  begin
    URI.parse(uri)
  rescue
    raise "@uri set to invalid uri '#{uri}'"
  end
end
boot(device) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 359
def boot(device)
  @boot_order << device # append
end
clock_timer(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 437
def clock_timer(options = {})
  if options[:name].nil?
    raise 'Clock timer name must be specified'
  end

  options.each do |key, value|
    case key
      when :name, :track, :tickpolicy, :frequency, :mode, :present
        if value.nil?
          raise "Value of timer option #{key} is nil"
        end
      else
        raise "Unknown clock timer option: #{key}"
    end
  end

  @clock_timers.push(options.dup)
end
cpu_feature(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 405
def cpu_feature(options = {})
  if options[:name].nil? || options[:policy].nil?
    raise 'CPU Feature name AND policy must be specified'
  end

  @cpu_features = [] if @cpu_features == UNSET_VALUE

  @cpu_features.push(name:   options[:name],
                     policy: options[:policy])
end
cputopology(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 456
def cputopology(options = {})
  if options[:sockets].nil? || options[:cores].nil? || options[:threads].nil?
    raise 'CPU topology must have all of sockets, cores and threads specified'
  end

  if @cpu_topology == UNSET_VALUE
    @cpu_topology = {}
  end

  @cpu_topology[:sockets] = options[:sockets]
  @cpu_topology[:cores] = options[:cores]
  @cpu_topology[:threads] = options[:threads]
end
disk_driver(options = {}) click to toggle source

Disk driver options for primary disk

# File lib/vagrant-libvirt/config.rb, line 635
def disk_driver(options = {})
  supported_opts = [:cache, :io, :copy_on_read, :discard, :detect_zeroes]
  @disk_driver_opts = options.select { |k,_| supported_opts.include? k }
end
finalize!() click to toggle source
# File lib/vagrant-libvirt/config.rb, line 812
def finalize!
  _default_uri if @uri == UNSET_VALUE

  # settings which _generate_uri
  @driver = 'kvm' if @driver == UNSET_VALUE
  @password = nil if @password == UNSET_VALUE
  @socket = nil if @socket == UNSET_VALUE

  # If uri isn't set then let's build one from various sources.
  # Default to passing false for qemu_use_session if it's not set.
  if @uri == UNSET_VALUE
    @uri = _generate_uri(@qemu_use_session == UNSET_VALUE ? false : @qemu_use_session)
  end

  finalize_from_uri
  finalize_proxy_command

  # forward port with id 'ssh'
  @forward_ssh_port = false if @forward_ssh_port == UNSET_VALUE

  @storage_pool_name = 'default' if @storage_pool_name == UNSET_VALUE
  @snapshot_pool_name = @storage_pool_name if @snapshot_pool_name == UNSET_VALUE
  @storage_pool_path = nil if @storage_pool_path == UNSET_VALUE
  @random_hostname = false if @random_hostname == UNSET_VALUE
  @management_network_device = 'virbr0' if @management_network_device == UNSET_VALUE
  @management_network_name = 'vagrant-libvirt' if @management_network_name == UNSET_VALUE
  @management_network_address = '192.168.121.0/24' if @management_network_address == UNSET_VALUE
  @management_network_mode = 'nat' if @management_network_mode == UNSET_VALUE
  @management_network_mac = nil if @management_network_mac == UNSET_VALUE
  @management_network_guest_ipv6 = 'yes' if @management_network_guest_ipv6 == UNSET_VALUE
  @management_network_autostart = false if @management_network_autostart == UNSET_VALUE
  @management_network_pci_bus = nil if @management_network_pci_bus == UNSET_VALUE
  @management_network_pci_slot = nil if @management_network_pci_slot == UNSET_VALUE
  @management_network_domain = nil if @management_network_domain == UNSET_VALUE
  @management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
  @management_network_keep = false if @management_network_keep == UNSET_VALUE

  # Domain specific settings.
  @title = '' if @title == UNSET_VALUE
  @description = '' if @description == UNSET_VALUE
  @uuid = '' if @uuid == UNSET_VALUE
  @memory = 512 if @memory == UNSET_VALUE
  @nodeset = nil if @nodeset == UNSET_VALUE
  @memory_backing = [] if @memory_backing == UNSET_VALUE
  @cpus = 1 if @cpus == UNSET_VALUE
  @cpuset = nil if @cpuset == UNSET_VALUE
  @cpu_mode = 'host-model' if @cpu_mode == UNSET_VALUE
  @cpu_model = if (@cpu_model == UNSET_VALUE) && (@cpu_mode == 'custom')
                 'qemu64'
               elsif @cpu_mode != 'custom'
                 ''
               else
                 @cpu_model
    end
  @cpu_topology = {} if @cpu_topology == UNSET_VALUE
  @cpu_fallback = 'allow' if @cpu_fallback == UNSET_VALUE
  @cpu_features = [] if @cpu_features == UNSET_VALUE
  @shares = nil if @shares == UNSET_VALUE
  @features = ['acpi','apic','pae'] if @features == UNSET_VALUE
  @features_hyperv = [] if @features_hyperv == UNSET_VALUE
  @clock_offset = 'utc' if @clock_offset == UNSET_VALUE
  @clock_timers = [] if @clock_timers == UNSET_VALUE
  @numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa
  @loader = nil if @loader == UNSET_VALUE
  @nvram = nil if @nvram == UNSET_VALUE
  @machine_type = nil if @machine_type == UNSET_VALUE
  @machine_arch = nil if @machine_arch == UNSET_VALUE
  @machine_virtual_size = nil if @machine_virtual_size == UNSET_VALUE
  @disk_device = @disk_bus == 'scsi' ? 'sda' : 'vda' if @disk_device == UNSET_VALUE
  @disk_bus = @disk_device.start_with?('sd') ? 'scsi' : 'virtio' if @disk_bus == UNSET_VALUE
  if @disk_controller_model == UNSET_VALUE
    if @disk_bus == 'scsi' or @disk_device.start_with?('sd') == 'sd'
      @disk_controller_model = 'virtio-scsi'
    else
      @disk_controller_model = nil
    end
  end
  @disk_driver_opts = {} if @disk_driver_opts == UNSET_VALUE
  @nic_model_type = nil if @nic_model_type == UNSET_VALUE
  @nested = false if @nested == UNSET_VALUE
  @volume_cache = nil if @volume_cache == UNSET_VALUE
  @kernel = nil if @kernel == UNSET_VALUE
  @cmd_line = '' if @cmd_line == UNSET_VALUE
  @initrd = '' if @initrd == UNSET_VALUE
  @dtb = nil if @dtb == UNSET_VALUE
  @graphics_type = 'vnc' if @graphics_type == UNSET_VALUE
  @graphics_autoport = 'yes' if @graphics_port == UNSET_VALUE
  @graphics_autoport = 'no' if @graphics_port != UNSET_VALUE
  if (@graphics_type != 'vnc' && @graphics_type != 'spice') ||
     @graphics_passwd == UNSET_VALUE
    @graphics_passwd = nil
  end
  @graphics_port = -1 if @graphics_port == UNSET_VALUE
  @graphics_ip = '127.0.0.1' if @graphics_ip == UNSET_VALUE
  @video_type = 'cirrus' if @video_type == UNSET_VALUE
  @video_vram = 16384 if @video_vram == UNSET_VALUE
  @video_accel3d = false if @video_accel3d == UNSET_VALUE
  @graphics_gl = @video_accel3d if @graphics_gl == UNSET_VALUE
  @sound_type = nil if @sound_type == UNSET_VALUE
  @keymap = 'en-us' if @keymap == UNSET_VALUE
  @kvm_hidden = false if @kvm_hidden == UNSET_VALUE
  @tpm_model = 'tpm-tis' if @tpm_model == UNSET_VALUE
  @tpm_type = 'passthrough' if @tpm_type == UNSET_VALUE
  @tpm_path = nil if @tpm_path == UNSET_VALUE
  @tpm_version = nil if @tpm_version == UNSET_VALUE
  @memballoon_enabled = nil if @memballoon_enabled == UNSET_VALUE
  @memballoon_model = 'virtio' if @memballoon_model == UNSET_VALUE
  @memballoon_pci_bus = '0x00' if @memballoon_pci_bus == UNSET_VALUE
  @memballoon_pci_slot = '0x0f' if @memballoon_pci_slot == UNSET_VALUE
  @nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
  @emulator_path = nil if @emulator_path == UNSET_VALUE

  @sysinfo = {} if @sysinfo == UNSET_VALUE

  # Boot order
  @boot_order = [] if @boot_order == UNSET_VALUE

  # Storage
  @disks = [] if @disks == UNSET_VALUE
  @cdroms = [] if @cdroms == UNSET_VALUE
  @cdroms.map! do |cdrom|
    cdrom[:dev] = _get_cdrom_dev(@cdroms) if cdrom[:dev].nil?
    cdrom
  end

  # Inputs
  @inputs = [{ type: 'mouse', bus: 'ps2' }] if @inputs == UNSET_VALUE

  # Channels
  if @channels == UNSET_VALUE
    @channels = []
    if @qemu_use_agent == true
      if @channels.all? { |channel| !channel.fetch(:target_name, '').start_with?('org.qemu.guest_agent.') }
        channel(:type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio')
      end
    end
  end

  # filter channels of anything explicitly disabled so it's possible to inject an entry to
  # avoid the automatic addition of the guest_agent above, and disable it from subsequent use.
  @channels = @channels.reject { |channel| channel[:disabled] }.tap {|channel| channel.delete(:disabled) }

  # PCI device passthrough
  @pcis = [] if @pcis == UNSET_VALUE

  # Random number generator passthrough
  @rng = {} if @rng == UNSET_VALUE

  # Watchdog device
  @watchdog_dev = {} if @watchdog_dev == UNSET_VALUE

  # USB device passthrough
  @usbs = [] if @usbs == UNSET_VALUE

  # Redirected devices
  @redirdevs = [] if @redirdevs == UNSET_VALUE
  @redirfilters = [] if @redirfilters == UNSET_VALUE

  # USB controller
  if @usbctl_dev == UNSET_VALUE
    @usbctl_dev = if !@usbs.empty? or !@redirdevs.empty? then {:model => 'qemu-xhci'} else {} end
  end

  # smartcard device
  @smartcard_dev = {} if @smartcard_dev == UNSET_VALUE

  # Suspend mode
  @suspend_mode = 'pause' if @suspend_mode == UNSET_VALUE

  # Autostart
  @autostart = false if @autostart == UNSET_VALUE

  # Attach mgmt network
  @mgmt_attach = true if @mgmt_attach == UNSET_VALUE

  # Additional QEMU commandline arguments
  @qemu_args = [] if @qemu_args == UNSET_VALUE

  # Additional QEMU commandline environment variables
  @qemu_env = {} if @qemu_env == UNSET_VALUE

  @qemu_use_agent = false if @qemu_use_agent == UNSET_VALUE

  @serials = [{:type => 'pty', :source => nil}] if @serials == UNSET_VALUE

  @host_device_exclude_prefixes = ['docker', 'macvtap', 'virbr', 'vnet'] if @host_device_exclude_prefixes == UNSET_VALUE
end
hyperv_feature(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 416
def hyperv_feature(options = {})
  if options[:name].nil? || options[:state].nil?
    raise 'Feature name AND state must be specified'
  end

  if options[:name] == 'spinlocks' && options[:retries].nil?
    raise 'Feature spinlocks requires retries parameter'
  end

  @features_hyperv = []  if @features_hyperv == UNSET_VALUE

  if options[:name] == 'spinlocks'
    @features_hyperv.push(name:   options[:name],
                       state: options[:state],
                       retries: options[:retries])
  else
    @features_hyperv.push(name:   options[:name],
                       state: options[:state])
  end
end
input(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 485
def input(options = {})
  if options[:type].nil? || options[:bus].nil?
    raise 'Input type AND bus must be specified'
  end

  @inputs = [] if @inputs == UNSET_VALUE

  @inputs.push(type: options[:type],
               bus:  options[:bus])
end
memorybacking(option, config = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 470
def memorybacking(option, config = {})
  case option
  when :source
    raise 'Source type must be specified' if config[:type].nil?
  when :access
    raise 'Access mode must be specified' if config[:mode].nil?
  when :allocation
    raise 'Allocation mode must be specified' if config[:mode].nil?
  end

  @memory_backing = [] if @memory_backing == UNSET_VALUE
  @memory_backing.push(name: option,
                       config: config)
end
merge(other) click to toggle source
Calls superclass method
# File lib/vagrant-libvirt/config.rb, line 1089
def merge(other)
  super.tap do |result|
    c = disks.dup
    c += other.disks
    result.disks = c

    c = cdroms.dup
    c += other.cdroms
    result.cdroms = c

    result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts)

    c = sysinfo == UNSET_VALUE ? {} : sysinfo.dup
    c.merge!(other.sysinfo) { |_k, x, y| x.respond_to?(:each_pair) ? x.merge(y) : x + y } if other.sysinfo != UNSET_VALUE
    result.sysinfo = c

    c = clock_timers.dup
    c += other.clock_timers
    result.clock_timers = c

    c = qemu_env != UNSET_VALUE ? qemu_env.dup : {}
    c.merge!(other.qemu_env) if other.qemu_env != UNSET_VALUE
    result.qemu_env = c

    if serials != UNSET_VALUE
      s = serials.dup
      s += other.serials
      result.serials = s
    end
  end
end
pci(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 530
def pci(options = {})
  if options[:bus].nil? || options[:slot].nil? || options[:function].nil?
    raise 'Bus AND slot AND function must be specified. Check `lspci` for that numbers.'
  end

  @pcis = [] if @pcis == UNSET_VALUE

  if options[:domain].nil?
    pci_domain = '0x0000'
  else
    pci_domain = options[:domain]
  end

  @pcis.push(domain:          pci_domain,
             bus:             options[:bus],
             slot:            options[:slot],
             function:        options[:function],
             guest_domain:    options[:guest_domain],
             guest_bus:       options[:guest_bus],
             guest_slot:      options[:guest_slot],
             guest_function:  options[:guest_function])
end
qemuargs(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 707
def qemuargs(options = {})
  @qemu_args = [] if @qemu_args == UNSET_VALUE

  @qemu_args << options if options[:value]
end
qemuenv(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 713
def qemuenv(options = {})
  @qemu_env = {} if @qemu_env == UNSET_VALUE

  @qemu_env.merge!(options)
end
random(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 520
def random(options = {})
  if !options[:model].nil? && options[:model] != 'random'
    raise 'The only supported rng backend is "random".'
  end

  @rng = {} if @rng == UNSET_VALUE

  @rng[:model] = options[:model]
end
redirdev(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 594
def redirdev(options = {})
  raise 'Type must be specified.' if options[:type].nil?

  @redirdevs = [] if @redirdevs == UNSET_VALUE

  @redirdevs.push(type: options[:type])
end
redirfilter(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 602
def redirfilter(options = {})
  raise 'Option allow must be specified.' if options[:allow].nil?

  @redirfilters = [] if @redirfilters == UNSET_VALUE

  @redirfilters.push(class: options[:class] || -1,
                     vendor: options[:vendor] || -1,
                     product: options[:product] || -1,
                     version: options[:version] || -1,
                     allow: options[:allow])
end
serial(options={}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 719
def serial(options={})
  @serials = [] if @serials == UNSET_VALUE

  options = {
    :type => "pty",
    :source => nil,
  }.merge(options)

  serial = {
    :type => options[:type],
    :source => options[:source],
  }

  @serials << serial
end
smartcard(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 614
def smartcard(options = {})
  if options[:mode].nil?
    raise 'Option mode must be specified.'
  elsif options[:mode] != 'passthrough'
    raise 'Currently only passthrough mode is supported!'
  elsif options[:type] == 'tcp' && (options[:source_mode].nil? || options[:source_host].nil? || options[:source_service].nil?)
    raise 'If using type "tcp", option "source_mode", "source_host" and "source_service" must be specified.'
  end

  if @smartcard_dev == UNSET_VALUE
    @smartcard_dev = {}
  end

  @smartcard_dev[:mode] = options[:mode]
  @smartcard_dev[:type] = options[:type] || 'spicevmc'
  @smartcard_dev[:source_mode] = options[:source_mode] if @smartcard_dev[:type] == 'tcp'
  @smartcard_dev[:source_host] = options[:source_host] if @smartcard_dev[:type] == 'tcp'
  @smartcard_dev[:source_service] = options[:source_service] if @smartcard_dev[:type] == 'tcp'
end
storage(storage_type, options = {}) click to toggle source

NOTE: this will run twice for each time it's needed- keep it idempotent

# File lib/vagrant-libvirt/config.rb, line 641
def storage(storage_type, options = {})
  if storage_type == :file
    if options[:device] == :cdrom
      _handle_cdrom_storage(options)
    else
      _handle_disk_storage(options)
    end
  end
end
usb(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 580
def usb(options = {})
  if (options[:bus].nil? || options[:device].nil?) && options[:vendor].nil? && options[:product].nil?
    raise 'Bus and device and/or vendor and/or product must be specified. Check `lsusb` for these.'
  end

  @usbs = [] if @usbs == UNSET_VALUE

  @usbs.push(bus:           options[:bus],
             device:        options[:device],
             vendor:        options[:vendor],
             product:       options[:product],
             startupPolicy: options[:startupPolicy])
end
usb_controller(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 567
def usb_controller(options = {})
  if options[:model].nil?
    raise 'USB controller model must be specified.'
  end

  if @usbctl_dev == UNSET_VALUE
      @usbctl_dev = {}
  end

  @usbctl_dev[:model] = options[:model]
  @usbctl_dev[:ports] = options[:ports] if options[:ports]
end
validate(machine) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 1000
def validate(machine)
  errors = _detected_errors

  # technically this shouldn't occur, but ensure that if somehow it does, it gets rejected.
  if @cpu_mode == 'host-passthrough' && @cpu_model != ''
    errors << "cannot set cpu_model with cpu_mode of 'host-passthrough'. leave model unset or switch mode."
  end

  # The @uri and @qemu_use_session should not conflict
  uri = _parse_uri(@uri)
  if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
    if @qemu_use_session != true
      errors << "the URI and qemu_use_session configuration conflict: uri:'#{@uri}' qemu_use_session:'#{@qemu_use_session}'"
    end
  end

  unless @qemu_use_agent == true || @qemu_use_agent == false
    errors << "libvirt.qemu_use_agent must be a boolean."
  end

  if !@nvram.nil? && @loader.nil?
    errors << "use of 'nvram' requires a 'loader' to be specified, please add one to the configuration"
  end

  if @qemu_use_agent == true
    # if qemu agent is used to obtain domain ip configuration, at least
    # one qemu channel has to be configured. As there are various options,
    # error out and leave configuration to the user
    unless machine.provider_config.channels.any? { |channel| channel[:target_name].start_with?("org.qemu.guest_agent") }
      errors << "qemu agent option enabled, but no qemu agent channel configured: please add at least one qemu agent channel to vagrant config"
    end
  end

  machine.provider_config.disks.each do |disk|
    if disk[:path] && (disk[:path][0] == '/')
      errors << "absolute volume paths like '#{disk[:path]}' not yet supported"
    end
  end

  machine.provider_config.serials.each do |serial|
    if serial[:source] and serial[:source][:path].nil?
      errors << "serial :source requires :path to be defined"
    end
  end

  # this won't be able to fully resolve the disks until the box has
  # been downloaded and any devices that need to be assigned to the
  # disks contained have been allocated
  disk_resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new
  begin
    disk_resolver.resolve(machine.provider_config.disks)
  rescue Errors::VagrantLibvirtError => e
    errors << "#{e}"
  end

  machine.config.vm.networks.each_with_index do |network, index|
    type, opts = network

    if opts[:mac]
      if opts[:mac] =~ /\A([0-9a-fA-F]{12})\z/
        opts[:mac] = opts[:mac].scan(/../).join(':')
      end
      unless opts[:mac] =~ /\A([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})\z/
        errors << "Configured NIC MAC '#{opts[:mac]}' is not in 'xx:xx:xx:xx:xx:xx' or 'xxxxxxxxxxxx' format"
      end
    end

    # only interested in public networks where portgroup is nil, as then source will be a host device
    if type == :public_network && opts[:portgroup] == nil
      devices = host_devices(machine)
      if !devices.include?(opts[:dev])
        errors << "network configuration #{index} for machine #{machine.name} is a public_network referencing host device '#{opts[:dev]}' which does not exist, consider adding ':dev => ....' referencing one of #{devices.join(", ")}"
      end
    end
  end

  if !machine.provider_config.volume_cache.nil? and machine.provider_config.volume_cache != UNSET_VALUE
    machine.ui.warn("Libvirt Provider: volume_cache is deprecated. Use disk_driver :cache => '#{machine.provider_config.volume_cache}' instead.")

    if !machine.provider_config.disk_driver_opts.empty?
      machine.ui.warn("Libvirt Provider: volume_cache has no effect when disk_driver is defined.")
    end
  end

  errors = validate_sysinfo(machine, errors)

  { 'Libvirt Provider' => errors }
end
watchdog(options = {}) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 553
def watchdog(options = {})
  if options[:model].nil?
    raise 'Model must be specified.'
  end

  if @watchdog_dev == UNSET_VALUE
      @watchdog_dev = {}
  end

  @watchdog_dev[:model] = options[:model]
  @watchdog_dev[:action] = options[:action] || 'reset'
end

Private Instance Methods

finalize_from_uri() click to toggle source
# File lib/vagrant-libvirt/config.rb, line 1123
def finalize_from_uri
  # Parse uri to extract individual components
  uri = _parse_uri(@uri)

  system_uri = uri.dup
  system_uri.path = '/system'
  @system_uri = system_uri.to_s if @system_uri == UNSET_VALUE

  # only set @connect_via_ssh if not explicitly to avoid overriding
  # and allow an error to occur if the @uri and @connect_via_ssh disagree
  @connect_via_ssh = uri.scheme.include? "ssh" if @connect_via_ssh == UNSET_VALUE

  # Set qemu_use_session based on the URI if it wasn't set by the user
  if @qemu_use_session == UNSET_VALUE
    if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
      @qemu_use_session = true
    else
      @qemu_use_session = false
    end
  end

  # Extract host values from uri if provided, otherwise nil
  @host = uri.host
  @port = uri.port
  # only override username if there is a value provided
  @username = nil if @username == UNSET_VALUE
  @username = uri.user if uri.user
  if uri.query
    params = CGI.parse(uri.query)
    @id_ssh_key_file = params['keyfile'].first if params.has_key?('keyfile')
  end

  finalize_id_ssh_key_file
end
finalize_id_ssh_key_file() click to toggle source
# File lib/vagrant-libvirt/config.rb, line 1166
def finalize_id_ssh_key_file
  # resolve based on the following roles
  #  1) if @connect_via_ssh is set to true, and id_ssh_key_file not current set,
  #     set default if the file exists
  #  2) if supplied the key name, attempt to expand based on user home
  #  3) otherwise set to nil

  if @connect_via_ssh == true && @id_ssh_key_file == UNSET_VALUE
    # set default if using ssh while allowing a user using nil to disable this
    id_ssh_key_file = resolve_ssh_key_file('id_rsa')
    id_ssh_key_file = nil if !File.file?(id_ssh_key_file)
  elsif @id_ssh_key_file != UNSET_VALUE
    id_ssh_key_file = resolve_ssh_key_file(@id_ssh_key_file)
  else
    id_ssh_key_file = nil
  end

  @id_ssh_key_file = id_ssh_key_file
end
finalize_proxy_command() click to toggle source
# File lib/vagrant-libvirt/config.rb, line 1186
def finalize_proxy_command
  if @connect_via_ssh
    if @proxy_command == UNSET_VALUE
      proxy_command = "ssh '#{@host}' "
      proxy_command += "-p #{@port} " if @port
      proxy_command += "-l '#{@username}' " if @username
      proxy_command += "-i '#{@id_ssh_key_file}' " if @id_ssh_key_file
      proxy_command += '-W %h:%p'
    else
      inputs = { host: @host }
      inputs << { port: @port } if @port
      inputs[:username] = @username if @username
      inputs[:id_ssh_key_file] = @id_ssh_key_file if @id_ssh_key_file

      proxy_command = String.new(@proxy_command)
      # avoid needing to escape '%' symbols
      inputs.each do |key, value|
        proxy_command.gsub!("{#{key}}", value)
      end
    end

    @proxy_command = proxy_command
  else
    @proxy_command = nil
  end
end
host_devices(machine) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 1213
def host_devices(machine)
  @host_devices ||= begin
    (
      machine.provider.driver.list_host_devices.map { |iface| iface.name } +
      machine.provider.driver.list_networks.map { |net| net.bridge_name }
    ).uniq.select do |dev|
      next if dev.empty?
      dev != "lo" && !@host_device_exclude_prefixes.any? { |exclude| dev.start_with?(exclude) }
    end
  end
end
resolve_ssh_key_file(key_file) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 1158
def resolve_ssh_key_file(key_file)
  # set ssh key for access to Libvirt host
  # if no slash, prepend $HOME/.ssh/
  key_file = "#{ENV['HOME']}/.ssh/#{key_file}" if key_file && key_file !~ /\A\//

  key_file
end
validate_sysinfo(machine, errors) click to toggle source
# File lib/vagrant-libvirt/config.rb, line 1225
def validate_sysinfo(machine, errors)
  valid_sysinfo = {
    'bios' => %w[vendor version date release],
    'system' => %w[manufacturer product version serial uuid sku family],
    'base board' => %w[manufacturer product version serial asset location],
    'chassis' => %w[manufacturer version serial asset sku],
    'oem strings' => nil,
  }

  machine.provider_config.sysinfo.each_pair do |block_name, entries|
    block_name = block_name.to_s
    unless valid_sysinfo.key?(block_name)
      errors << "invalid sysinfo element '#{block_name}'; smbios sysinfo elements supported: #{valid_sysinfo.keys.join(', ')}"
      next
    end

    if valid_sysinfo[block_name].nil?
      # assume simple array of text entries
      entries.each do |entry|
        if entry.respond_to?(:to_str)
          if entry.to_s.empty?
            machine.ui.warn("Libvirt Provider: 'sysinfo.#{block_name}' contains an empty or nil entry and will be discarded")
          end
        else
          errors << "sysinfo.#{block_name} expects entries to be stringy, got #{entry.class} containing '#{entry}'"
        end
      end
    else
      entries.each_pair do |entry_name, entry_text|
        entry_name = entry_name.to_s
        unless valid_sysinfo[block_name].include?(entry_name)
          errors << "'sysinfo.#{block_name}' does not support entry name '#{entry_name}'; entries supported: #{valid_sysinfo[block_name].join(', ')}"
          next
        end

        # this allows removal of entries specified by other Vagrantfile's in the hierarchy
        if entry_text.to_s.empty?
          machine.ui.warn("Libvirt Provider: sysinfo.#{block_name}.#{entry_name} is nil or empty and therefore has no effect.")
        end
      end
    end
  end

  errors
end