class VagrantPlugins::ProviderLibvirt::Config
Constants
- ARCH_SUPPORT_CPU
list of architectures that support cpu based on github.com/libvirt/libvirt/tree/master/src/cpu
Attributes
Autostart
Channels
If use ssh tunnel to connect to Libvirt.
Default host prefix (alternative to use project folder name)
Storage
A hypervisor name to access via Libvirt.
Forward port with id 'ssh'
The name of the server, where Libvirtd is running.
internal helper attributes
ID SSH key file
Inputs
Libvirt default network
Configure the memballoon
Attach mgmt network
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
Password for Libvirt connection.
PCI device passthrough
Additional qemuargs arguments
Additional qemuenv arguments
Use QEMU Agent to get ip address
Use QEMU session instead of system
Turn on to prevent hostname conflicts
Redirected devices
Random number device passthrough
serial consoles
smartcard device
Libvirt storage pool where the base image snapshot shall be stored
Path towards the Libvirt socket
Libvirt storage pool name, where box image and instance snapshots will be stored.
Suspend mode
Configure sysinfo values
System connection information
Domain specific settings used while creating new domain.
Sets the information for connecting to a host TPM device Only supports socket-based TPMs
manually specify URI will supersede most other options if provided
USB controller
USB device passthrough
The username to access Libvirt.
Watchdog device
Public Class Methods
# File lib/vagrant-libvirt/config.rb, line 232 def initialize @logger = Log4r::Logger.new("vagrant_libvirt::config") @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 @management_network_driver_iommu = UNSET_VALUE @management_network_iface_name = UNSET_VALUE @management_network_model_type = 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 @memtunes = {} @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 @cpu_affinity = UNSET_VALUE @shares = UNSET_VALUE @features = UNSET_VALUE @features_hyperv = UNSET_VALUE @clock_absolute = UNSET_VALUE @clock_adjustment = UNSET_VALUE @clock_basis = UNSET_VALUE @clock_offset = UNSET_VALUE @clock_timezone = UNSET_VALUE @clock_timers = [] @launchsecurity_data = UNSET_VALUE @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_address_type = 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_websocket = 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 = [] @floppies = [] # 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
# File lib/vagrant-libvirt/config.rb, line 864 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
# File lib/vagrant-libvirt/config.rb, line 443 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
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 882 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 += "#{URI.encode_www_form_component(@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
# File lib/vagrant-libvirt/config.rb, line 406 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
# File lib/vagrant-libvirt/config.rb, line 425 def _get_floppy_dev(floppies) exist = Hash[floppies.collect { |x| [x[:dev], true] }] # fda - fdb curr = 'a'.ord while curr <= 'b'.ord dev = "fd#{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 two floppies may be attached at a time' end
# File lib/vagrant-libvirt/config.rb, line 757 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
# File lib/vagrant-libvirt/config.rb, line 806 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], address_type: options[:address_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
# File lib/vagrant-libvirt/config.rb, line 784 def _handle_floppy_storage(options = {}) # <disk type='file' device='floppy'> # <source file='/var/lib/libvirt/images/floppy.vfd'/> # <target dev='fda' bus='fdc'/> # </disk> # # note the target dev will need to be changed with each floppy drive (fda or fdb) options = { bus: 'fdc', path: nil }.merge(options) floppy = { dev: options[:dev], bus: options[:bus], path: options[:path] } @floppies << floppy end
# File lib/vagrant-libvirt/config.rb, line 933 def _parse_uri(uri) begin URI.parse(uri) rescue raise "@uri set to invalid uri '#{uri}'" end end
# File lib/vagrant-libvirt/config.rb, line 402 def boot(device) @boot_order << device # append end
# File lib/vagrant-libvirt/config.rb, line 499 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
# File lib/vagrant-libvirt/config.rb, line 467 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
# File lib/vagrant-libvirt/config.rb, line 532 def cpuaffinitiy(affinity = {}) if @cpu_affinity == UNSET_VALUE @cpu_affinity = {} end affinity.each do |vcpu, cpuset| @cpu_affinity[vcpu] = cpuset end end
# File lib/vagrant-libvirt/config.rb, line 518 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 for primary disk
# File lib/vagrant-libvirt/config.rb, line 738 def disk_driver(options = {}) supported_opts = [:cache, :io, :copy_on_read, :discard, :detect_zeroes, :type] @disk_driver_opts = options.select { |k,_| supported_opts.include? k } end
# File lib/vagrant-libvirt/config.rb, line 941 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 true for qemu_use_session if it's not set. if @uri == UNSET_VALUE @uri = _generate_uri(@qemu_use_session == UNSET_VALUE ? true : @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 # Domain specific settings. @title = '' if @title == UNSET_VALUE @description = '' if @description == UNSET_VALUE @uuid = '' if @uuid == UNSET_VALUE @machine_type = nil if @machine_type == UNSET_VALUE @machine_arch = nil if @machine_arch == 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 = if @cpu_mode == UNSET_VALUE # only some architectures support the cpu element if @machine_arch.nil? || ARCH_SUPPORT_CPU.include?(@machine_arch.downcase) 'host-model' else nil end else @cpu_mode end @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_affinity = {} if @cpu_affinity == 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_absolute = nil if @clock_absolute == UNSET_VALUE @clock_adjustment = nil if @clock_adjustment == UNSET_VALUE @clock_basis = 'utc' if @clock_basis == UNSET_VALUE @clock_offset = 'utc' if @clock_offset == UNSET_VALUE @clock_timezone = nil if @clock_timezone == UNSET_VALUE @clock_timers = [] if @clock_timers == UNSET_VALUE @launchsecurity_data = nil if @launchsecurity_data == UNSET_VALUE @numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa @loader = nil if @loader == UNSET_VALUE @nvram = nil if @nvram == 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_address_type = nil if @disk_address_type == UNSET_VALUE @disk_driver_opts = {} if @disk_driver_opts == UNSET_VALUE @nic_model_type = 'virtio' 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 = nil if @initrd == UNSET_VALUE @dtb = nil if @dtb == UNSET_VALUE @graphics_type = 'vnc' if @graphics_type == UNSET_VALUE @graphics_autoport = @graphics_type != 'spice' && @graphics_port == UNSET_VALUE ? 'yes' : nil if (@graphics_type != 'vnc' && @graphics_type != 'spice') || @graphics_passwd == UNSET_VALUE @graphics_passwd = nil end @graphics_port = @graphics_type == 'spice' ? nil : -1 if @graphics_port == UNSET_VALUE @graphics_websocket = @graphics_type == 'spice' ? nil : -1 if @graphics_websocket == UNSET_VALUE @graphics_ip = @graphics_type == 'spice' ? nil : '127.0.0.1' if @graphics_ip == UNSET_VALUE @video_accel3d = false if @video_accel3d == UNSET_VALUE @graphics_gl = @video_accel3d if @graphics_gl == UNSET_VALUE @video_type = @video_accel3d ? 'virtio' : 'cirrus' if @video_type == UNSET_VALUE @video_vram = 16384 if @video_vram == 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 @floppies = [] if @floppies == UNSET_VALUE @floppies.map! do |floppy| floppy[:dev] = _get_floppy_dev(@floppies) if floppy[:dev].nil? floppy end # Inputs @inputs = [{ type: 'mouse', bus: 'ps2' }] if @inputs == UNSET_VALUE # Channels @channels = [] if @channels == UNSET_VALUE 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 if @graphics_type == 'spice' if @channels.all? { |channel| !channel.fetch(:target_name, '').start_with?('com.redhat.spice.') } channel(:type => 'spicevmc', :target_name => 'com.redhat.spice.0', :target_type => 'virtio') 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 # management network options @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 @management_network_driver_iommu = false if @management_network_driver_iommu == UNSET_VALUE @management_network_iface_name = nil if @management_network_iface_name == UNSET_VALUE @management_network_model_type = @nic_model_type if @management_network_model_type == UNSET_VALUE @host_device_exclude_prefixes = ['docker', 'macvtap', 'virbr', 'vnet'] if @host_device_exclude_prefixes == UNSET_VALUE end
# File lib/vagrant-libvirt/config.rb, line 478 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
# File lib/vagrant-libvirt/config.rb, line 588 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
# File lib/vagrant-libvirt/config.rb, line 576 def launchsecurity(options = {}) if options.fetch(:type) != 'sev' raise "Launch security type only supports SEV. Explicitly set 'sev' as a type" end @launchsecurity_data = {} @launchsecurity_data[:type] = options[:type] @launchsecurity_data[:cbitpos] = options[:cbitpos] || 47 @launchsecurity_data[:reducedPhysBits] = options[:reducedPhysBits] || 1 @launchsecurity_data[:policy] = options[:policy] || "0x0003" end
# File lib/vagrant-libvirt/config.rb, line 542 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
# File lib/vagrant-libvirt/config.rb, line 557 def memtune(config={}) if config[:type].nil? raise "Missing memtune type" end unless ['hard_limit', 'soft_limit', 'swap_hard_limit'].include? config[:type] raise "Memtune type '#{config[:type]}' not allowed (hard_limit, soft_limit, swap_hard_limit are allowed)" end if config[:value].nil? raise "Missing memtune value" end opts = config[:options] || {} opts[:unit] = opts[:unit] || "KiB" @memtunes[config[:type]] = { value: config[:value], config: opts } end
# File lib/vagrant-libvirt/config.rb, line 1266 def merge(other) super.tap do |result| result.boot_order = other.boot_order != [] ? other.boot_order : boot_order c = disks.dup c += other.disks result.disks = c c = cdroms.dup c += other.cdroms result.cdroms = c c = floppies.dup c += other.floppies result.floppies = c result.memtunes = memtunes.merge(other.memtunes) result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts) result.inputs = inputs != UNSET_VALUE ? inputs.dup + (other.inputs != UNSET_VALUE ? other.inputs : []) : other.inputs 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
# File lib/vagrant-libvirt/config.rb, line 633 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
# File lib/vagrant-libvirt/config.rb, line 836 def qemuargs(options = {}) @qemu_args = [] if @qemu_args == UNSET_VALUE @qemu_args << options if options[:value] end
# File lib/vagrant-libvirt/config.rb, line 842 def qemuenv(options = {}) @qemu_env = {} if @qemu_env == UNSET_VALUE @qemu_env.merge!(options) end
# File lib/vagrant-libvirt/config.rb, line 623 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
# File lib/vagrant-libvirt/config.rb, line 697 def redirdev(options = {}) raise 'Type must be specified.' if options[:type].nil? @redirdevs = [] if @redirdevs == UNSET_VALUE @redirdevs.push(type: options[:type]) end
# File lib/vagrant-libvirt/config.rb, line 705 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
# File lib/vagrant-libvirt/config.rb, line 848 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
# File lib/vagrant-libvirt/config.rb, line 717 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
NOTE: this will run twice for each time it's needed- keep it idempotent
# File lib/vagrant-libvirt/config.rb, line 744 def storage(storage_type, options = {}) if storage_type == :file case options[:device] when :cdrom _handle_cdrom_storage(options) when :floppy _handle_floppy_storage(options) else _handle_disk_storage(options) end end end
# File lib/vagrant-libvirt/config.rb, line 683 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
# File lib/vagrant-libvirt/config.rb, line 670 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
# File lib/vagrant-libvirt/config.rb, line 1158 def validate(machine) errors = _detected_errors unless @machine_arch.nil? || ARCH_SUPPORT_CPU.include?(@machine_arch.downcase) unsupported = [:cpu_mode, :cpu_model, :nested, :cpu_features, :cpu_topology, :numa_nodes] cpu_support_required_by = unsupported.select { |x| value = instance_variable_get("@#{x.to_s}") next if value.nil? # not set is_bool = !!value == value next if is_bool && !value # boolean and set to false next if !is_bool && value.empty? # not boolean, but empty '', [], {} true } unless cpu_support_required_by.empty? errors << "Architecture #{@machine_arch} does not support /domain/cpu XML, which is required when setting the config options #{cpu_support_required_by.join(", ")}" end end # 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 unless @cpu_model != '' || @cpu_features.empty? errors << "cannot set cpu_features with cpu_model unset, please set a model or skip setting features." 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 errors = validate_networks(machine, errors) 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 # if run via a session, then qemu will be run with user permissions, make sure the user # has permissions to access the host paths otherwise there will be an error triggered if machine.provider_config.qemu_use_session synced_folders(machine).fetch(:"9p", []).each do |_, options| unless File.readable?(options[:hostpath]) errors << "9p synced_folder cannot mount host path #{options[:hostpath]} into guest #{options[:guestpath]} when using qemu session as executing user does not have permissions to read the directory on the user." end end unless synced_folders(machine)[:"virtiofs"].nil? machine.ui.warn("Note: qemu session may not support virtiofs for synced_folders, use 9p or enable use of qemu:///system context unless you know what you are doing") end end if [@clock_absolute, @clock_adjustment, @clock_timezone].count {|clock| !clock.nil?} > 1 errors << "At most, only one of [clock_absolute, clock_adjustment, clock_timezone] may be set." end errors = validate_sysinfo(machine, errors) { 'Libvirt Provider' => errors } end
# File lib/vagrant-libvirt/config.rb, line 656 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
# File lib/vagrant-libvirt/config.rb, line 1310 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 set empty string @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
# File lib/vagrant-libvirt/config.rb, line 1353 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
# File lib/vagrant-libvirt/config.rb, line 1373 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
# File lib/vagrant-libvirt/config.rb, line 1345 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
# File lib/vagrant-libvirt/config.rb, line 1400 def validate_networks(machine, errors) begin networks = configured_networks(machine, @logger) rescue Errors::VagrantLibvirtError => e errors << "#{e}" return end return if networks.empty? networks.each_with_index do |network, index| if network[:mac] if network[:mac] =~ /\A([0-9a-fA-F]{12})\z/ network[:mac] = network[:mac].scan(/../).join(':') end unless network[:mac] =~ /\A([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})\z/ errors << "Configured NIC MAC '#{network[: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 network[:iface_type] == :public_network && network[:portgroup] == nil exclude_prefixes = @host_device_exclude_prefixes # for qemu sessions the management network injected will be a public_network trying to use a libvirt managed device if index == 0 and machine.provider_config.mgmt_attach and machine.provider_config.qemu_use_session == true exclude_prefixes.delete('virbr') end devices = machine.provider.driver.host_devices.select do |dev| next if dev.empty? dev != "lo" && !exclude_prefixes.any? { |exclude| dev.start_with?(exclude) } end hostdev = network.fetch(:dev, 'eth0') if !devices.include?(hostdev) errors << "network configuration #{index} for machine #{machine.name} is a public_network referencing host device '#{hostdev}' which does not exist, consider adding ':dev => ....' referencing one of #{devices.join(", ")}" end end unless network[:iface_name].nil? restricted_devnames = ['vnet', 'vif', 'macvtap', 'macvlan'] if restricted_devnames.any? { |restricted| network[:iface_name].start_with?(restricted) } errors << "network configuration for machine #{machine.name} with setting :libvirt__iface_name => '#{network[:iface_name]}' starts with a restricted prefix according to libvirt docs https://libvirt.org/formatdomain.html#overriding-the-target-element, please use a device name that does not start with one of #{restricted_devnames.join(", ")}" end end end errors end
# File lib/vagrant-libvirt/config.rb, line 1451 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