tf-ansible-workflow

Terraform/Ansible Workflow for Libvirt
git clone https://git.in0rdr.ch/tf-ansible-workflow.git
Log | Files | Refs | Pull requests |Archive

vms.tf (6511B)


      1 # based on the example from:
      2 # https://github.com/dmacvicar/terraform-provider-libvirt/tree/master/examples/v0.12/ubuntu
      3 
      4 locals {
      5     all_hosts = merge(libvirt_domain.host, libvirt_domain.hosts_type2)
      6 }
      7 
      8 terraform {
      9   required_providers {
     10     libvirt = {
     11       source = "dmacvicar/libvirt"
     12       version = "0.6.14"
     13     }
     14   }
     15 }
     16 
     17 # todo: LIBVIRT_DEFAULT_URI does not work?
     18 provider "libvirt" {
     19     uri = "qemu:///system"
     20 }
     21 
     22 # libvirt pool for the images in the path of the tf module
     23 resource "libvirt_pool" "pool" {
     24     name = var.project
     25     type = "dir"
     26     path = abspath("${path.module}/libvirt-pool-${var.project}")
     27 }
     28 
     29 # backing image to save disk space for multiple vms
     30 # https://kashyapc.fedorapeople.org/virt/lc-2012/snapshots-handout.html
     31 resource "libvirt_volume" "base_volume" {
     32     name   = "${var.project}-base"
     33     pool   = libvirt_pool.pool.name
     34     source = var.baseimage
     35     format = var.baseimage_format
     36 
     37     # todo: required for "terraform destroy"
     38     depends_on = [libvirt_pool.pool]
     39 }
     40 
     41 resource "libvirt_volume" "volume" {
     42     # unique image (based on backing file) for each host
     43     for_each       = toset(var.hosts)
     44 
     45     name           = "${var.project}-cow-${each.value}"
     46     pool           = libvirt_pool.pool.name
     47     base_volume_id = libvirt_volume.base_volume.id
     48     size           = var.disk
     49 }
     50 
     51 
     52 # ssh private key
     53 resource "tls_private_key" "id_rsa" {
     54     algorithm = "RSA"
     55 }
     56 resource "local_sensitive_file" "ssh_private_key" {
     57     content           = tls_private_key.id_rsa.private_key_pem
     58     filename          = "${path.module}/../ssh/id_rsa"
     59     file_permission   = "0600"
     60 }
     61 resource "local_sensitive_file" "ssh_public_key" {
     62     content           = tls_private_key.id_rsa.public_key_openssh
     63     filename          = "${path.module}/../ssh/id_rsa.pub"
     64 }
     65 
     66 
     67 # cloud init config files
     68 data "template_file" "user_data" {
     69     template = file("${path.module}/${var.cloudinit_userdata}")
     70 }
     71 data "template_file" "network_config" {
     72     template = file("${path.module}/${var.cloudinit_networkconfig}")
     73 }
     74 # for more info about paramater check this out
     75 # https://github.com/dmacvicar/terraform-provider-libvirt/blob/master/website/docs/r/cloudinit.html.markdown
     76 # Use CloudInit to add our ssh-key to the instance
     77 # you can add also meta_data field
     78 resource "libvirt_cloudinit_disk" "commoninit" {
     79     name           = var.cloudinit_iso
     80     user_data      = data.template_file.user_data.rendered
     81     network_config = data.template_file.network_config.rendered
     82     pool           = libvirt_pool.pool.name
     83 }
     84 
     85 resource "libvirt_domain" "host" {
     86     # create each host
     87     for_each = toset(var.hosts)
     88 
     89     name   = each.value
     90     memory = var.memory
     91     vcpu   = var.vcpu
     92 
     93     cloudinit = libvirt_cloudinit_disk.commoninit.id
     94     qemu_agent = false
     95 
     96     network_interface {
     97         network_name   = libvirt_network.network.name
     98         wait_for_lease = true
     99     }
    100 
    101     # IMPORTANT: this is a known bug on cloud images, since they expect a console
    102     # we need to pass it
    103     # https://bugs.launchpad.net/cloud-images/+bug/1573095
    104     console {
    105         type        = "pty"
    106         target_port = "0"
    107         target_type = "serial"
    108     }
    109 
    110     console {
    111         type        = "pty"
    112         target_type = "virtio"
    113         target_port = "1"
    114     }
    115 
    116     disk {
    117         volume_id = libvirt_volume.volume[each.value].id
    118     }
    119 
    120     graphics {
    121         type        = "spice"
    122         listen_type = "address"
    123         autoport    = true
    124     }
    125 }
    126 
    127 resource "libvirt_network" "network" {
    128     name = var.project
    129 
    130     # mode can be: "nat" (default), "none", "route", "bridge"
    131     mode      = "nat"
    132     autostart = true
    133 
    134     #  the domain used by the DNS server in this network
    135     domain    = var.domain
    136 
    137     #  list of subnets the addresses allowed for domains connected
    138     # also derived to define the host addresses
    139     # also derived to define the addresses served by the DHCP server
    140     addresses = [var.network]
    141 
    142     # (optional) the bridge device defines the name of a bridge device
    143     # which will be used to construct the virtual network.
    144     # (only necessary in "bridge" mode)
    145     # bridge = "br7"
    146 
    147     # (optional) the MTU for the network. If not supplied, the underlying device's
    148     # default is used (usually 1500)
    149     # mtu = 9000
    150 
    151     # (Optional) DNS configuration
    152     dns {
    153         # (Optional, default false)
    154         # Set to true, if no other option is specified and you still want to
    155         # enable dns.
    156         enabled = true
    157         # (Optional, default false)
    158         # true: DNS requests under this domain will only be resolved by the
    159         # virtual network's own DNS server
    160         # false: Unresolved requests will be forwarded to the host's
    161         # upstream DNS server if the virtual network's DNS server does not
    162         # have an answer.
    163         local_only = true
    164 
    165         # (Optional) one or more DNS forwarder entries.  One or both of
    166         # "address" and "domain" must be specified.  The format is:
    167         # forwarders {
    168         #     address = "my address"
    169         #     domain = "my domain"
    170         #  }
    171         #
    172 
    173         # (Optional) one or more DNS host entries.  Both of
    174         # "ip" and "hostname" must be specified.  The format is:
    175         # hosts  {
    176         #     hostname = "my_hostname"
    177         #     ip = "my.ip.address.1"
    178         #   }
    179         # hosts {
    180         #     hostname = "my_hostname"
    181         #     ip = "my.ip.address.2"
    182         #   }
    183         #
    184 
    185         # not possible due to cyclic dependency
    186         # use Ansible instead and amend manually, see ('../ansible/dhcp-static-hosts.yml')
    187         # dynamic "hosts" {
    188         #     for_each = var.hosts
    189         #     content {
    190         #         hostname = hosts.value
    191         #         ip = tolist(libvirt_domain.host[hosts.value].network_interface)[0]["addresses"][0]
    192         #     }
    193         # }
    194 
    195         # (Optional) one or more static routes.
    196         # "cidr" and "gateway" must be specified. The format is:
    197         # routes {
    198         #     cidr = "10.17.0.0/16"
    199         #     gateway = "10.18.0.2"
    200         #   }
    201     }
    202 
    203     dhcp {
    204         enabled = true
    205     }
    206 }
    207 
    208 resource "null_resource" "update_cloudinit" {
    209     triggers = {
    210         # when the ssh key in the local cloudinit file changes
    211         key_id   = local_sensitive_file.ssh_public_key.id
    212     }
    213     provisioner "local-exec" {
    214         # recreate cloudinit config
    215         command = "echo '${templatefile("${path.module}/templates/cloud_init.cfg.tpl", { public_key = tls_private_key.id_rsa.public_key_openssh })}' > ./cloud_init.cfg"
    216     }
    217 }