diff --git a/lib/fog/libvirt/compute.rb b/lib/fog/libvirt/compute.rb index 14f6c20..c12f579 100644 --- a/lib/fog/libvirt/compute.rb +++ b/lib/fog/libvirt/compute.rb @@ -22,6 +22,7 @@ class Compute < Fog::Service collection :nodes model :nic collection :nics + model :tpm request_path 'fog/libvirt/requests/compute' request :list_domains diff --git a/lib/fog/libvirt/models/compute/server.rb b/lib/fog/libvirt/models/compute/server.rb index 805898f..d691b70 100644 --- a/lib/fog/libvirt/models/compute/server.rb +++ b/lib/fog/libvirt/models/compute/server.rb @@ -36,6 +36,8 @@ class Server < Fog::Compute::Server attribute :guest_agent attribute :video attribute :virtio_rng + attribute :tpm + attribute :tpm_device attribute :state @@ -58,6 +60,7 @@ def initialize(attributes={} ) super defaults.merge(attributes) initialize_nics initialize_volumes + initialize_tpm @user_data = attributes.delete(:user_data) end @@ -411,6 +414,27 @@ def to_xml xml.backend(virtio_rng[:backend_path], :model => virtio_rng.fetch(:backend_model, "random")) end + if tpm[:enable] + if tpm_device.model == "spapr-tpm-proxy" + tpm_model_type = "spapr-tpm-proxy" + else + tpm_model_type = "tpm-#{tpm_device.model}" + end + + xml.tpm(:model => tpm_model_type) do + if tpm_device.type == "passthrough" + xml.backend(:type => tpm_device.type) do + xml.device(:path => tpm_device.passthrough_device_path) + end + else + xml.backend(:type => tpm_device.type, :version => tpm_device.version) + end + if tpm_device.model == "spapr" || tpm_device.model == "spapr-tpm-proxy" + xml.address(:type => tpm_device.par_address_type, :reg => tpm_device.spar_address_reg) + end + end + end + if arch == "s390x" xml.controller(:type => "scsi", :index => "0", :model => "virtio-scsi") xml.console(:type => "pty") do @@ -504,6 +528,12 @@ def initialize_volumes end end + def initialize_tpm + if tpm[:enable] + self.tpm_device = TPM.new(tpm, arch) + end + end + def create_or_clone_volume options = {:name => volume_name || default_volume_name} # Check if a disk template was specified @@ -561,6 +591,7 @@ def defaults :video => {:type => "virtio", :heads => 1}, :virtio_rng => {}, :firmware_features => { "secure-boot" => "no" }, + :tpm => {:enable => false, :id => "tpm0"} } end diff --git a/lib/fog/libvirt/models/compute/tpm.rb b/lib/fog/libvirt/models/compute/tpm.rb new file mode 100644 index 0000000..43094a5 --- /dev/null +++ b/lib/fog/libvirt/models/compute/tpm.rb @@ -0,0 +1,90 @@ +require 'fog/core/model' + +module Fog + module Libvirt + class Compute + class TPM < Fog::Model + # Currently Qemu only allows for one TPM device + + identity :id + attribute :arch + attribute :model + attribute :type + attribute :version + attribute :device_path + attribute :spapr_address_type + attribute :spapr_address_reg + + # Models + # crb - TCG PC Client Platform TPM Profile (PTP) Specification (2017) + # tis - TCG PC Client Specific TPM Interface Specification (TIS) (2013) + # spapr - Used with pSeries (ppc64) + # spapr-tpm-proxy - Used with pSeries (ppc64), this is only used with 'passthrough' type + # + MODELS_X86_64 = ['crb', 'tis'].freeze + MODELS_PPC64 = ['spapr', 'spapr-tpm-proxy'].freeze + MODELS_ARM64 = ['tis'].freeze + + # Versions + # + VERSIONS = ['1.2', '2.0'].freeze + + # Types + # + TYPES = ['emulator', 'passthrough'].freeze + + def initialize(attributes = {}, arch = "") + @arch = arch + super defaults.merge(attributes) + raise Fog::Errors::Error.new("#{model} is not a supported tpm model") if new? && !supported_models.include?(model) + raise Fog::Errors::Error.new("#{type} is not a supported tpm type") if new? && !TYPES.include?(type) + end + + def new? + id.nil? + end + + def save + raise Fog::Errors::Error.new('Creating a new TPM device is not yet implemented. Contributions welcome!') + end + + def destroy + raise Fog::Errors::Error.new('Destroying a TPM device is not yet implemented. Contributions welcome!') + end + + def supported_models + case @arch + when "x86_64" + MODELS_X86_64 + when "ppc64" + MODELS_PPC64 + when "arm64" || "aarch64" + MODELS_ARM64 + else + raise Fog::Errors::Error.new('CPU Architecture does not have any supported TPM models!') + end + end + + def defaults + case @arch + when "x86_64" + { :model => "crb", :type => "emulator", :version => "2.0", :passthrough_device_path => "/dev/tpm0" } + when "ppc64" + { + :model => "spapr", + :type => "emulator", + :version => "2.0", + :passthrough_device_path => "/dev/tpmrm0", + :spapr_address_type => "spapr-vio", + :spapr_address_reg => "0x00004000" + } + when "arm64" || "aarch64" + { :model => "tis", :type => "emulator", :version => "2.0", :passthrough_device_path => "/dev/tpm0" } + else + {} + end + end + end + end + end +end