• Infrastructure
    • terraform
    • packer
  • Networking
    • consul
  • Security
    • vault
    • boundary
  • Applications
    • nomad
    • waypoint
    • vagrant
  • HashiCorp Cloud Platform

    A fully managed platform to automate infrastructure on any cloud with HashiCorp products.

    • consul
    • terraform
    • vault
    • packerbeta
    Visit cloud.hashicorp.com
  • Overview
  • Tutorials
  • Docs
  • Plugins
  • Community
GitHubInstall PackerTry HCP Packer
  • About External Plugins

      • 1&1
      • Alicloud ECS
      • Alicloud Import
      • Anka Registry Push
      • VM Clone
      • VM Create
      • Ansible (Remote)
      • Ansible Local
      • Overview
      • Amazon AMI
      • Parameter Store
      • Secrets Manager
      • Overview
      • chroot
      • EBS
      • EBS Surrogate
      • EBS Volume
      • Instance
      • Amazon Import
      • Overview
      • ARM
      • chroot
      • DTL
      • Azure DTL Artifact
      • Chef Client
      • Chef Solo
      • CloudStack
      • Converge
      • digitalocean
      • digitalocean-import
      • Docker
      • Docker Import
      • Docker Push
      • Docker Save
      • Docker Tag
      • Overview
      • Commit
      • Repository
      • Tree
      • Google Cloud Platform
      • googlecompute-export
      • googlecompute-import
      • Overview
      • Receipt
      • Overview
      • Toppings
      • Overview
      • Coffees
      • Ingredients
      • Overview
      • Order
      • Hetzner Cloud
      • HuaweiCloud
      • HyperOne
      • Overview
      • ISO
      • VMCX
      • InSpec
      • JDCloud
      • Kamatera
      • Linode
      • Libvirt
      • LXC
      • LXD
      • Naver Cloud
      • OpenStack
      • Overview
      • Classic
      • OCI
      • Overview
      • BSU
      • BSU Surrogate
      • BSU Volume
      • chroot
      • Overview
      • ISO
      • PVM
      • ProfitBricks
      • Overview
      • Clone
      • ISO
      • Puppet Masterless
      • Puppet Server
      • QEMU
      • Salt Masterless
      • Scaleway
      • SSH Key
      • Tencent Cloud
      • Triton
      • UCloud
      • UCloud Import
      • upcloud
      • upcloud-import
      • Vagrant
      • Vagrant
      • Vagrant Cloud
      • Overview
      • ISO
      • OVF
      • VM
      • Overview
      • Clone
      • ISO
      • vSphere
      • vSphere Template
      • Overview
      • ISO
      • VMX
      • Vultr
      • Yandex
      • yandex-export
      • yandex-import
Type '/' to Search
Community
v0.3.1

Libvirt

Type: libvirt Artifact BuilderId: thomasklein94.libvirt

The Libvirt Builder is able to create Libvirt volumes on your libvirt hypervisor by copying an image from a http source, by using already existing volumes as a backing store, or creating an empty one and starting a libvirt domain with these volumes attached.

Libvirt builder also supports cloudinit images during build.

Before looking at the configuration options and examples, you might also want to check out and familiarize yourself with libvirt's domain specification and libvirt's storage pool and volume concepts.

Required

  • libvirt_uri (string) - Libvirt URI

Optional

  • communicator (communicator.Config) - Communicator configuration See Packer's documentation for more.

  • domain_name (string) - The libvirt name of the domain (virtual machine) running your build If not specified, a random name with the prefix packer- will be used

  • memory (int) - The amount of memory to use when building the VM in megabytes. This defaults to 512 megabytes.

  • vcpu (int) - The number of cpus to use when building the VM. The default is 1 CPU.

  • network_interface ([]network.NetworkInterface) - Network interface attachments. See Network for more.

  • communicator_interface (string) - The alias of the network interface used for the SSH/WinRM connections See Communicators and network interfaces

  • volume ([]volume.Volume) - See Volumes

  • artifact_volume_alias (string) - The alias of the drive designated to be the artifact. To learn more, see Volumes

  • boot_devices ([]string) - Device(s) from which to boot, defaults to hard drive (first volume) Available boot devices are: hd, network, cdrom

  • graphics ([]DomainGraphic) - See Graphics and video, headless domains.

  • network_address_source (string) - The alias of the network interface designated as the communicator interface. Can be either agent, lease or arp. Default value is agent. To learn more, see Communicators and network interfaces in the builder documentation.

  • shutdown_mode (string) - Packer will instruct libvirt to use this mode to properly shut down the virtual machine before it attempts to destroy it. Available modes are: acpi, guest, initctl, signal and paravirt. If not set, libvirt will choose the method of shutdown it considers the best.

  • shutdown_timeout (duration string | ex: "1h5m2s") - After succesfull provisioning, Packer will wait this long for the virtual machine to gracefully stop before it destroys it. If not specified, Packer will wait for 5 minutes.

Aliases

Libvirt offers a way to add one alias per device. Libvirt builder uses this to find out which volume should be the artifact in case there are multiple volume configurations present. Finding the communicator interface is similar in fashion. There are reasonable defaults built into the builder to ease onboarding but they will produce a warning and it's recommended to use aliases.

The identifier must consist only of the following characters: [a-zA-Z0-9_-]. Libvirt also requires the identifier to start with ua-, but libvirt builder will take care of that for you and prepend every alias with ua- before applying the domain definition to libvirt.

Graceful shutdown

To ensure all changes were synced to the artifact volume, after a successful provisioning, the Libvirt plugin will try to gracefully terminate the builder instance by sending a shutdown command to libvirt and wait up to shutdown_timeout before forcefully destroys the domain. Libvirt supports multiple way to shut down a domain, which can be controlled by the shutdown_mode attribute.

Volumes

Libvirt uses volumes to attach as disks, to boot from and to persist data to. Libvirt Builder treats volumes as sources and possible artifacts. Arbitrary number of volumes can be attached to a builder domain with specifying a volume { } block for each. The volume which will be the artifact of the build has to be marked with alias = "artifact".

A volume defined with a source MUST NOT EXISTS BEFORE the build and WILL BE DESTROYED at the end of the build. The only exception is when the volume marked as an artifact in which case a successful build prevents libvirt builder from deleting the volume.

If a volume does not have a source defined and does not marked as an artifact, the volume must exists before the build, and will not be destroyed at the end of the build.

  • pool (string) - Specifies the name of the storage pool (managed by libvirt) where the disk resides. If not specified the pool named default will be used

  • name (string) - Providing a name for the volume which is unique to the pool. (For a disk pool, the name must be combination of the source device path device and next partition number to be created. For example, if the source device path is /dev/sdb and there are no partitions on the disk, then the name must be sdb1 with the next name being sdb2 and so on.) If not provided, a name will be generated in a format of <domain_name>-<postfix> where postfix will be either the alias or a random id. For cloudinit, the generated name will be <domain_name>-cloudinit

  • source (*VolumeSource) - Provides information about the underlying storage allocation of the volume. This may not be available for some pool types.

  • size (string) - Providing the total storage allocation for the volume. This may be smaller than the logical capacity if the volume is sparsely allocated. It may also be larger than the logical capacity if the volume has substantial metadata overhead. If omitted when creating a volume, the volume will be fully allocated at time of creation. If set to a value smaller than the capacity, the pool has the option of deciding to sparsely allocate a volume. It does not have to honour requests for sparse allocation though. Different types of pools may treat sparse volumes differently. For example, the logical pool will not automatically expand volume's allocation when it gets full;

  • capacity (string) - Providing the logical capacity for the volume. This value is in bytes by default, but a unit attribute can be specified with the same semantics as for allocation This is compulsory when creating a volume.

  • readonly (bool) - If true, it indicates the device cannot be modified by the guest.

  • target_dev (string) - The target element controls the bus / device under which the disk is exposed to the guest OS. The dev attribute indicates the "logical" device name. The actual device name specified is not guaranteed to map to the device name in the guest OS. Treat it as a device ordering hint. If no bus and target_dev attribute is specified, it defaults to target_dev = "sda" with bus = "scsi"

  • bus (string) - The optional bus attribute specifies the type of disk device to emulate; possible values are driver specific, with typical values being ide, scsi, virtio, xen, usb, sata, or sd sd since 1.1.2. If omitted, the bus type is inferred from the style of the device name (e.g. a device named 'sda' will typically be exported using a SCSI bus).

  • alias (string) - To help users identifying devices they care about, every device can have an alias which must be unique within the domain. Additionally, the identifier must consist only of the following characters: [a-zA-Z0-9_-].

  • format (string) - Specifies the volume format type, like qcow, qcow2, vmdk, raw. If omitted, the storage pool's default format will be used.

Backing-store volume source

Backing-store source instructs libvirt to use an already presented volume as a base for this volume.

  • volume (string) - Specifies the name of storage volume (managed by libvirt) used as the disk source.

  • path (string) - The file backing the volume. Mutually exclusive with pool and volume args!

Example

volume {
  target_dev = "sda"
  bus        = "sata"

  pool = "default"
  name = "custom-image"

  source {
    type = "backing-store"

    pool   = "base-images"
    volume = "ubuntu-22.04-lts"
  }
  capacity = "20G"
}
volume {
  target_dev = "sda"
  bus        = "sata"
 
  pool = "default"
  name = "custom-image"
 
  source {
    type = "backing-store"
 
    pool   = "base-images"
    volume = "ubuntu-22.04-lts"
  }
  capacity = "20G"
}

Cloning a volume

If you wish to clone a volume instead of using a backing store overlay described above, You have the option to use the cloning source type.

  • volume (string) - Specifies the name of storage volume (managed by libvirt) used as the disk source.

Example

volume {
  target_dev = "sda"
  bus        = "sata"

  pool = "default"
  name = "custom-image"

  source {
    type = "cloning"

    pool   = "base-images"
    volume = "ubuntu-22.04-lts"
  }
}
volume {
  target_dev = "sda"
  bus        = "sata"
 
  pool = "default"
  name = "custom-image"
 
  source {
    type = "cloning"
 
    pool   = "base-images"
    volume = "ubuntu-22.04-lts"
  }
}

Cloud-init volume source

Linux domains running in a libvirt environment can be set up with the NoCloud cloud-init datasource. This means a small ISO image with the label CIDATA will be assembled at the machine running packer and will be uploaded to the volume. To assemble an ISO image, one of the following commands must be installed at the machine running packer and must be available in the PATH: xorriso, mkisofs, hdiutil or oscdimg.

For cloud-init backed sources, the size and capacity attributes can be omitted for the volume.

  • meta_data (*string) - [optional] NoCloud instance metadata as string. If not present, a default one will be generated with the instance-id set to the same value as the domain name If you want to set network config, see the network_config attribute

  • user_data (*string) - [optional] CloudInit user-data as string. See cloud-init documentation for more

  • network_config (*string) - [optional] Network configuration for cloud-init to be picked up. User-data cannot change an instance’s network configuration. In the absence of network configuration in any sources, Cloud-init will write out a network configuration that will issue a DHCP request on a “first” network interface. Read more about the possible format and features at cloud-init documentation.

Example:

volume {
  target_dev = "sdb"
  bus        = "sata"
  source {
    type = "cloud-init"

    meta_data = jsonencode({
      "instance-id" = "i-abcdefghijklm"
      "hostname"    = "my-packer-builder"
    })

    user_data =  format("#cloud-config\n%s", jsonencode({
      packages = [
            "qemu-guest-agent",
        ]
        runcmd = [
            ["systemctl", "enable", "--now", "qemu-guest-agent"],
        ]
        ssh_authorized_keys = [
            data.sshkey.install.public_key,
        ]
    }))

    network_config = jsonencode({
      version = 2
        ethernets = {
            eth = {
                match = {
                    name = "en*"
                }
                dhcp4 = true
            }
        }
    })
  }
}
volume {
  target_dev = "sdb"
  bus        = "sata"
  source {
    type = "cloud-init"
 
    meta_data = jsonencode({
      "instance-id" = "i-abcdefghijklm"
      "hostname"    = "my-packer-builder"
    })
 
    user_data =  format("#cloud-config\n%s", jsonencode({
      packages = [
            "qemu-guest-agent",
        ]
        runcmd = [
            ["systemctl", "enable", "--now", "qemu-guest-agent"],
        ]
        ssh_authorized_keys = [
            data.sshkey.install.public_key,
        ]
    }))
 
    network_config = jsonencode({
      version = 2
        ethernets = {
            eth = {
                match = {
                    name = "en*"
                }
                dhcp4 = true
            }
        }
    })
  }
}

External volume source

An external volume source defines a volume source that is external (or remote) to the libvirt hypervisor. This usually means a cloud image or installation media from the web or local machine. It's using go-getter under the hood with support for HTTP, HTTPS, S3, SMB and local files. The files will be cached by Packer.

  • checksum (string) - The checksum and the type of the checksum for the download

  • urls ([]string) - A list of URLs from where this volume can be obtained

Example:

volume {
  alias = "artifact"

  pool = "base-images"
  name = "ubuntu-22.04-lts"

  source {
    type     = "external"
    urls     = ["https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64-disk-kvm.img"]
    checksum = "2a0d8745dee674a7f3038d627d39ff68e5d7276f97866a4abd9ebfcb3df5fa05"
  }

  format = "qcow2"

  capacity = "1G"

  bus        = "sata"
  target_dev = "sda"
}
volume {
  alias = "artifact"
 
  pool = "base-images"
  name = "ubuntu-22.04-lts"
 
  source {
    type     = "external"
    urls     = ["https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64-disk-kvm.img"]
    checksum = "2a0d8745dee674a7f3038d627d39ff68e5d7276f97866a4abd9ebfcb3df5fa05"
  }
 
  format = "qcow2"
 
  capacity = "1G"
 
  bus        = "sata"
  target_dev = "sda"
}

Network

Network interfaces can be attached to a builder domain by adding a network_interface { } block for each. Currently only managed and bridge networks are supported.

  • type (string) - [required] Type of attached network interface
  • mac (string) - [optional] If needed, a MAC address can be specified for the network interface. If not specified, Libvirt will generate and assign a random MAC address

  • alias (string) - [optional] To help users identifying devices they care about, every device can have an alias which must be unique within the domain. Additionally, the identifier must consist only of the following characters: [a-zA-Z0-9_-].

  • model (string) - [optional] Defines how the interface should be modeled for the domain. Typical values for QEMU and KVM include: ne2k_isa i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio. If nothing is specified, virtio will be used as a default.

Communicators and network interfaces

If an SSH or WinRM address is specified in the communicator block, packer will use that address to communicate with the builder domain.

If no SSH or WinRM address is specified, the libvirt builder tries to find an address for initiating communications. If only one network interface is specified for a builder domain, and there is no communicator_interface specified for the domain, then that interface will be used as the interface for communication.

If more than one network interface is specified, the communicator interface must be tagged by setting the same alias as specified with the communicator_interface domain attribute (which is "communicator" by default.)

The network_address_source domain attribute controls how the address discovery will take place. There are three possible way to discover a domain's virtual address:

  • agent: this is the most reliable method for getting an address for the domain, but it requires qemu-guest-agent running in the domain. This is the default method for domains.
  • lease: if for some reason, the guest agent can not be started, but the communicator interface is connected to one of libvirt's managed networks, you can use lease to see what DHCP lease was offered for the interface.
  • arp: this method relies on the libvirt host ARP table to find an IP address associated with the MAC address given to the domain.

Examples

For connecting to a managed network

network_interface {
  type    = "managed"
  network = "my-managed-network"
}
network_interface {
  type    = "managed"
  network = "my-managed-network"
}

For connecting to a bridge

network_interface {
  type   = "bridge"
  bridge = "br0"
}
network_interface {
  type   = "bridge"
  bridge = "br0"
}

Graphics and video, headless domains

Libvirt builder creates a headless domain by default with no video card or monitor attached to it. Most linux distributions and cloud images are fine with this setup, but you might need to add a video card and a graphical interface to your machine.

You can add one (or more) graphic device to your machine by using the graphics { } block. If at least one graphic device is added to the builder configuration, a video device with the model virtio will automatically be added to the domain. Currently, there is no option to specify or customize just a video device for a domain.

  • type (string) - Type of the graphic defined with this block. Required. Must be either vnc or sdl.
  • display (string) - An X11 Display number where the SDL window will be sent. Required for type sdl
  • port (int) - TCP port used for VNC server to listen on. The number zero means the hypervisor will pick a free port randomly. If not set, the autoport feature will be used.

Debugging a build

By default, Libvirt builder assigns two serial console to the domain with the aliases serial-console and virtual-console. You can use your virtual manager to connect to one of these consoles for debug.

If you don't have access to a virtual machine manager, if specifying the -debug flag and PACKER_LOG=1 environment variable to packer simultaneously while setting the PACKER_LIBVIRT_STREAM_CONSOLE to one of the console aliases, the builder will connect to that console and logs any message the domain sends to that console. In no way, shape or form should this be used in any production or serious setup!

A simple builder definition example

source "libvirt" "example" {
  libvirt_uri = "qemu:///system"
  network_interface {
      type  = "managed"
      alias = "communicator"
  }

  volume {
    alias = "artifact"
    source {
        type   = "backing-store"
        pool   = "base-images"
        volume = "ubuntu-22.04-base"
    }

    capacity   = "10G"
    target_dev = "sda"
    bus        = "sata"
  }
}

build {
  sources = ["source.libvirt.example"]
}
source "libvirt" "example" {
  libvirt_uri = "qemu:///system"
  network_interface {
      type  = "managed"
      alias = "communicator"
  }
 
  volume {
    alias = "artifact"
    source {
        type   = "backing-store"
        pool   = "base-images"
        volume = "ubuntu-22.04-base"
    }
 
    capacity   = "10G"
    target_dev = "sda"
    bus        = "sata"
  }
}
 
build {
  sources = ["source.libvirt.example"]
}
github logoEdit this page
IntroGuidesDocsCommunityPrivacySecurityPress KitConsent Manager