diff --git a/README.md b/README.md index 6005d40..090cdaa 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ In the table below, build passing means that specific version combination of Vag - [USB Redirector Devices](#usb-redirector-devices) - [Random number generator passthrough](#random-number-generator-passthrough) - [Watchdog·Device](#watchdog-device) +- [Smartcard device](#smartcard-device) - [CPU Features](#cpu-features) - [No box and PXE boot](#no-box-and-pxe-boot) - [SSH Access To VM](#ssh-access-to-vm) @@ -881,6 +882,27 @@ Vagrant.configure("2") do |config| end ``` +## Smartcard device +A virtual smartcard device can be supplied to the guest via the `libvirt.smartcard` element. The option `mode` is mandatory and currently only value `passthrough` is supported. The value `spicevmc` for option `type` is default value and can be supressed. On using `type = tcp`, the options `source_mode`, `source_host` and `source_service` are mandatory. + +```ruby +Vagrant.configure("2") do |config| + config.vm.provider :libvirt do |libvirt| + # Add smartcard device with type 'spicevmc' + libvirt.smartcard :mode => 'passthrough', :type => 'spicevmc' + end +end +``` + +```ruby +Vagrant.configure("2") do |config| + config.vm.provider :libvirt do |libvirt| + # Add smartcard device with type 'tcp' + domain.smartcard :mode => 'passthrough', :type => 'tcp', :source_mode => 'bind', :source_host => '127.0.0.1', :source_service => '2001' + end +end +``` + ## CPU features You can specify CPU feature policies via `libvirt.cpu_feature`. Available diff --git a/lib/vagrant-libvirt/action/create_domain.rb b/lib/vagrant-libvirt/action/create_domain.rb index fbc77d0..a4866a8 100644 --- a/lib/vagrant-libvirt/action/create_domain.rb +++ b/lib/vagrant-libvirt/action/create_domain.rb @@ -96,6 +96,9 @@ module VagrantPlugins @redirdevs = config.redirdevs @redirfilters = config.redirfilters + # smartcard device + @smartcard_dev = config.smartcard_dev + # RNG device passthrough @rng = config.rng @@ -266,6 +269,10 @@ module VagrantPlugins end end + if not @smartcard_dev.empty? + env[:ui].info(" -- smartcard device: mode=#{@smartcard_dev[:mode]}, type=#{@smartcard_dev[:type]}") + end + env[:ui].info(" -- Command line : #{@cmd_line}") # Create libvirt domain. diff --git a/lib/vagrant-libvirt/config.rb b/lib/vagrant-libvirt/config.rb index 7346b57..055850b 100644 --- a/lib/vagrant-libvirt/config.rb +++ b/lib/vagrant-libvirt/config.rb @@ -126,6 +126,9 @@ module VagrantPlugins attr_accessor :redirdevs attr_accessor :redirfilters + # smartcard device + attr_accessor :smartcard_dev + # Suspend mode attr_accessor :suspend_mode @@ -218,6 +221,9 @@ module VagrantPlugins @redirdevs = UNSET_VALUE @redirfilters = UNSET_VALUE + # smartcard device + @smartcard_dev = UNSET_VALUE + # Suspend mode @suspend_mode = UNSET_VALUE @@ -398,6 +404,26 @@ module VagrantPlugins allow: options[:allow]) end + 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 def storage(storage_type, options = {}) if storage_type == :file @@ -604,6 +630,9 @@ module VagrantPlugins @redirdevs = [] if @redirdevs == UNSET_VALUE @redirfilters = [] if @redirfilters == UNSET_VALUE + # smartcard device + @smartcard_dev = {} if @smartcard_dev == UNSET_VALUE + # Suspend mode @suspend_mode = 'pause' if @suspend_mode == UNSET_VALUE diff --git a/lib/vagrant-libvirt/templates/domain.xml.erb b/lib/vagrant-libvirt/templates/domain.xml.erb index de127b8..5da9083 100644 --- a/lib/vagrant-libvirt/templates/domain.xml.erb +++ b/lib/vagrant-libvirt/templates/domain.xml.erb @@ -188,6 +188,18 @@ <% end %> + <% unless @smartcard_dev.empty? -%> + <% if @smartcard_dev[:mode] == 'passthrough' %> + <% if @smartcard_dev[:type] == 'tcp' %> + + + + <% else %> + + <% end %> + <% end %> + <% end -%> + <% if @tpm_path -%> <%# TPM Device -%> diff --git a/spec/unit/templates/domain_all_settings.xml b/spec/unit/templates/domain_all_settings.xml index 929a03a..51d7a19 100644 --- a/spec/unit/templates/domain_all_settings.xml +++ b/spec/unit/templates/domain_all_settings.xml @@ -117,6 +117,8 @@ + + diff --git a/spec/unit/templates/domain_defaults.xml b/spec/unit/templates/domain_defaults.xml index 39abbf7..fdbd1eb 100644 --- a/spec/unit/templates/domain_defaults.xml +++ b/spec/unit/templates/domain_defaults.xml @@ -40,5 +40,6 @@ + diff --git a/spec/unit/templates/domain_spec.rb b/spec/unit/templates/domain_spec.rb index 8a2a357..d79e433 100644 --- a/spec/unit/templates/domain_spec.rb +++ b/spec/unit/templates/domain_spec.rb @@ -59,6 +59,7 @@ describe 'templates/domain' do domain.redirfilter(class: '0x0b', vendor: '0x08e6', product: '0x3437', version: '2.00', allow: 'yes') domain.watchdog(model: 'i6300esb', action: 'reset') + domain.smartcard(mode: 'passthrough') domain.tpm_path = '/dev/tpm0' end let(:test_file) { 'domain_all_settings.xml' }