dmacvicar / terraform-provider-libvirt

Terraform provider to provision infrastructure with Linux's KVM using libvirt
Apache License 2.0
1.54k stars 457 forks source link

"apply" fails when using XSLT #999

Closed greenseeker closed 1 year ago

greenseeker commented 1 year ago

System Information

Linux distribution

Debian 11 (terraform) Almalinux 9.1 (kvm)

Terraform version

1.3.2

Provider and libvirt versions

registry.terraform.io/dmacvicar/libvirt v0.7.1 libvirt-8.5.0-7.3.el9_1.x86_64


Description of Issue/Question

I'm trying to utilize XSLT to enable HyperV enlightenments on my Windows VMs but this causes apply failure.

Setup

compiled tf files:

terraform {
   required_providers {
      libvirt = {
         source = "dmacvicar/libvirt"
      }
   }
}

provider "libvirt" {
   uri = "qemu+ssh://root@cyrodiil.tamriel.lab/system"
}

resource "libvirt_network" "chinchilla-net" {
  name = "chinchilla"
  mode = "nat"
  domain = "chinchilla.lab"
  addresses = ["192.168.2.1/24"]
  dns {
    enabled = true
  }
  dhcp {
    enabled = true
  }
}

resource "libvirt_volume" "chinchilla-win2016-disk" {
  name   = "chinchilla-win2016.qcow2"
  size   = 53687091200
  pool   = "images"
  base_volume_pool = "tmpl"
  base_volume_name = "win2016base.qcow2"
}

resource "libvirt_cloudinit_disk" "chinchilla-win2016-cloudinit-disk" {
  name   = "chinchilla-win2016-cloudinit.iso"
  pool   = "boot"
  user_data = data.template_file.chinchilla_win2016_user_data.rendered
}

data "template_file" "chinchilla_win2016_user_data" {
  template = file("${path.module}/cloudinit-win2016.yaml")
}

resource "libvirt_domain" "chinchilla-win2016-vm" {
  name   = "chinchilla-win2016"
  autostart = true
  qemu_agent = true
  memory = 16384
  vcpu   = 3
  cpu {
    mode = "host-passthrough"
  }
  xml {
    xslt = "win2016-hyperv-enlightenments.xsl"
  }

  network_interface {
    network_id = libvirt_network.chinchilla-net.id
    wait_for_lease = true
  }

  disk {
    volume_id = libvirt_volume.chinchilla-win2016-disk.id
  }

  cloudinit = libvirt_cloudinit_disk.chinchilla-win2016-cloudinit-disk.id

  console {
    type = "pty"
    target_port = 0
    target_type = "serial"
  }

  console {
    type = "pty"
    target_type = "virtio"
    target_port = 1
  }

  graphics {
    type = "vnc"
    listen_type = "address"
    autoport = true
  }
}

Steps to Reproduce Issue

terraform apply error:

2023-02-07T19:14:01.048-0500 [INFO]  provider.terraform-provider-libvirt_v0.7.1: 2023/02/07 19:14:01 [ERROR] Failed to run xsltproc (is it installed?): timestamp=2023-02-07T19:14:01.048-0500
2023-02-07T19:14:01.049-0500 [ERROR] provider.terraform-provider-libvirt_v0.7.1: Response contains error diagnostic: diagnostic_summary="error applying XSLT stylesheet: exit status 4" tf_provider_addr=provider tf_rpc=ApplyResourceChange @caller=github.com/hashicorp/terraform-plugin-go@v0.14.0/tfprotov5/internal/diag/diagnostics.go:55 diagnostic_severity=ERROR tf_req_id=3e292b92-6f06-48c2-038a-169bb5b0281d tf_resource_type=libvirt_domain @module=sdk.proto diagnostic_detail= tf_proto_version=5.3 timestamp=2023-02-07T19:14:01.049-0500
2023-02-07T19:14:01.052-0500 [ERROR] vertex "libvirt_domain.chinchilla-win2016-vm" error: error applying XSLT stylesheet: exit status 4
╷
│ Error: error applying XSLT stylesheet: exit status 4
│
│   with libvirt_domain.chinchilla-win2016-vm,
│   on win2016.tf line 23, in resource "libvirt_domain" "chinchilla-win2016-vm":
│   23: resource "libvirt_domain" "chinchilla-win2016-vm" {
│
╵
2023-02-07T19:14:01.063-0500 [INFO]  provider.terraform

Full terraform apply output here: https://pastebin.com/GEPnDLF6

xsltproc is installed on both the KVM host and the terraform system. In fact, I used it to validate my xsl sheet before adding it to my project.

win2016-hyperv-enlightenments.xsl:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="1.0">

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="features">
    <xsl:copy>
      <xsl:apply-templates />
      <xsl:element name="hyperv">
        <xsl:attribute name="mode">custom</xsl:attribute>
        <xsl:element name="relaxed">
          <xsl:attribute name="state">on</xsl:attribute>
        </xsl:element>
        <xsl:element name="vapic">
          <xsl:attribute name="state">on</xsl:attribute>
        </xsl:element>
        <xsl:element name="spinlocks">
          <xsl:attribute name="state">on</xsl:attribute>
          <xsl:attribute name="retries">8191</xsl:attribute>
        </xsl:element>
        <xsl:element name="vpindex">
          <xsl:attribute name="state">on</xsl:attribute>
        </xsl:element>
        <xsl:element name="synic">
          <xsl:attribute name="state">on</xsl:attribute>
        </xsl:element>
        <xsl:element name="stimer">
          <xsl:attribute name="state">on</xsl:attribute>
        </xsl:element>
        <xsl:element name="reset">
          <xsl:attribute name="state">on</xsl:attribute>
        </xsl:element>
      </xsl:element>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="clock">
    <xsl:copy>
      <xsl:apply-templates />
      <xsl:attribute name="offset">localtime</xsl:attribute>
      <xsl:element name="timer">
        <xsl:attribute name="name">rtc</xsl:attribute>
        <xsl:attribute name="tickpolicy">catchup</xsl:attribute>
      </xsl:element>
      <xsl:element name="timer">
        <xsl:attribute name="name">pit</xsl:attribute>
        <xsl:attribute name="tickpolicy">delay</xsl:attribute>
      </xsl:element>
      <xsl:element name="timer">
        <xsl:attribute name="name">hpet</xsl:attribute>
        <xsl:attribute name="present">no</xsl:attribute>
      </xsl:element>
      <xsl:element name="timer">
        <xsl:attribute name="name">hypervclock</xsl:attribute>
        <xsl:attribute name="present">yes</xsl:attribute>
      </xsl:element>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Additional information:

I've disabled both apparmor and selinux for testing, but saw no difference.

alexandre-janniaux commented 1 year ago

Hi, I've referenced the ticket in my commit since it's the same mistake. :)

xslt is a string that must be assigned with the content of your XSLT, not the filename. You need to change this:

  xml {
    xslt = "win2016-hyperv-enlightenments.xsl"
  }

into this

  xml {
    xslt = file("win2016-hyperv-enlightenments.xsl")
  }
greenseeker commented 1 year ago

@alexandre-janniaux, thanks, that did the trick.

jeje232 commented 1 month ago

I didn't have installed xsltproc in the horchestrator... Nice! Thanks.