openstack_compute_instance_v2

Manages a V2 VM instance resource within OpenStack.

Example Usage

Basic Instance

resource "openstack_compute_instance_v2" "basic" {
  name            = "basic"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  metadata = {
    this = "that"
  }

  network {
    name = "my_network"
  }
}

Instance With Attached Volume

resource "openstack_blockstorage_volume_v3" "myvol" {
  name = "myvol"
  size = 1
}

resource "openstack_compute_instance_v2" "myinstance" {
  name            = "myinstance"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  network {
    name = "my_network"
  }
}

resource "openstack_compute_volume_attach_v2" "attached" {
  instance_id = openstack_compute_instance_v2.myinstance.id
  volume_id   = openstack_blockstorage_volume_v3.myvol.id
}

Boot From Volume

resource "openstack_compute_instance_v2" "boot-from-volume" {
  name            = "boot-from-volume"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  block_device {
    uuid                  = "<image-id>"
    source_type           = "image"
    volume_size           = 5
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    name = "my_network"
  }
}

Boot From an Existing Volume

resource "openstack_blockstorage_volume_v3" "myvol" {
  name     = "myvol"
  size     = 5
  image_id = "<image-id>"
}

resource "openstack_compute_instance_v2" "boot-from-volume" {
  name            = "bootfromvolume"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  block_device {
    uuid                  = openstack_blockstorage_volume_v3.myvol.id
    source_type           = "volume"
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    name = "my_network"
  }
}

Boot Instance, Create Volume, and Attach Volume as a Block Device

resource "openstack_compute_instance_v2" "instance_1" {
  name            = "instance_1"
  image_id        = "<image-id>"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  block_device {
    uuid                  = "<image-id>"
    source_type           = "image"
    destination_type      = "local"
    boot_index            = 0
    delete_on_termination = true
  }

  block_device {
    source_type           = "blank"
    destination_type      = "volume"
    volume_size           = 1
    boot_index            = 1
    delete_on_termination = true
  }
}

Boot Instance and Attach Existing Volume as a Block Device

resource "openstack_blockstorage_volume_v3" "volume_1" {
  name = "volume_1"
  size = 1
}

resource "openstack_compute_instance_v2" "instance_1" {
  name            = "instance_1"
  image_id        = "<image-id>"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  block_device {
    uuid                  = "<image-id>"
    source_type           = "image"
    destination_type      = "local"
    boot_index            = 0
    delete_on_termination = true
  }

  block_device {
    uuid                  = openstack_blockstorage_volume_v3.volume_1.id
    source_type           = "volume"
    destination_type      = "volume"
    boot_index            = 1
    delete_on_termination = true
  }
}

Instance With Multiple Networks

resource "openstack_networking_floatingip_v2" "myip" {
  pool = "my_pool"
}

resource "openstack_compute_instance_v2" "multi-net" {
  name            = "multi-net"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  network {
    name = "my_first_network"
  }

  network {
    name = "my_second_network"
  }
}

resource "openstack_compute_floatingip_associate_v2" "myip" {
  floating_ip = openstack_networking_floatingip_v2.myip.address
  instance_id = openstack_compute_instance_v2.multi-net.id
  fixed_ip    = openstack_compute_instance_v2.multi-net.network.1.fixed_ip_v4
}

Instance With Personality

resource "openstack_compute_instance_v2" "personality" {
  name            = "personality"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  personality {
    file    = "/path/to/file/on/instance.txt"
    content = "contents of file"
  }

  network {
    name = "my_network"
  }
}

Instance with Multiple Ephemeral Disks

resource "openstack_compute_instance_v2" "multi-eph" {
  name            = "multi_eph"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  block_device {
    boot_index            = 0
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "image"
    uuid                  = "<image-id>"
  }

  block_device {
    boot_index            = -1
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "blank"
    volume_size           = 1
    guest_format          = "ext4"
  }

  block_device {
    boot_index            = -1
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "blank"
    volume_size           = 1
  }
}

Instance with Boot Disk and Swap Disk

resource "openstack_compute_flavor_v2" "flavor-with-swap" {
  name  = "flavor-with-swap"
  ram   = "8096"
  vcpus = "2"
  disk  = "20"
  swap  = "4096"
}

resource "openstack_compute_instance_v2" "vm-swap" {
  name            = "vm_swap"
  flavor_id       = openstack_compute_flavor_v2.flavor-with-swap.id
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  block_device {
    boot_index            = 0
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "image"
    uuid                  = "<image-id>"
  }

  block_device {
    boot_index            = -1
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "blank"
    guest_format          = "swap"
    volume_size           = 4
  }
}

Instance with User Data (cloud-init)

resource "openstack_compute_instance_v2" "instance_1" {
  name            = "basic"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]
  user_data       = "#cloud-config\nhostname: instance_1.example.com\nfqdn: instance_1.example.com"

  network {
    name = "my_network"
  }
}

user_data can come from a variety of sources: inline, read in from the file function, or the template_cloudinit_config resource.

Argument Reference

The following arguments are supported:

The network block supports:

The block_device block supports:

The scheduler_hints block supports:

    [">=", "$free_ram_mb", "1024"]

The personality block supports:

The vendor_options block supports:

Attributes Reference

The following attributes are exported:

Notes

Multiple Ephemeral Disks

It's possible to specify multiple block_device entries to create an instance with multiple ephemeral (local) disks. In order to create multiple ephemeral disks, the sum of the total amount of ephemeral space must be less than or equal to what the chosen flavor supports.

The following example shows how to create an instance with multiple ephemeral disks:

resource "openstack_compute_instance_v2" "foo" {
  name            = "terraform-test"
  security_groups = ["default"]

  block_device {
    boot_index            = 0
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "image"
    uuid                  = "<image uuid>"
  }

  block_device {
    boot_index            = -1
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "blank"
    volume_size           = 1
  }

  block_device {
    boot_index            = -1
    delete_on_termination = true
    destination_type      = "local"
    source_type           = "blank"
    volume_size           = 1
  }
}

Instances and Security Groups

When referencing a security group resource in an instance resource, always use the _name_ of the security group. If you specify the ID of the security group, Terraform will remove and reapply the security group upon each call. This is because the OpenStack Compute API returns the names of the associated security groups and not their IDs.

Note the following example:

resource "openstack_networking_secgroup_v2" "sg_1" {
  name = "sg_1"
}

resource "openstack_compute_instance_v2" "foo" {
  name            = "terraform-test"
  security_groups = [openstack_networking_secgroup_v2.sg_1.name]
}

Instances and Ports

Neutron Ports are a great feature and provide a lot of functionality. However, there are some notes to be aware of when mixing Instances and Ports:

resource "openstack_networking_port_v2" "port_1" {
  name           = "port_1"
  admin_state_up = "true"

  network_id = "0a1d0a27-cffa-4de3-92c5-9d3fd3f2e74d"

  security_group_ids = [
    "2f02d20a-8dca-49b7-b26f-b6ce9fddaf4f",
    "ca1e5ed7-dae8-4605-987b-fadaeeb30461",
  ]
}

resource "openstack_compute_instance_v2" "instance_1" {
  name = "instance_1"

  network {
    port = openstack_networking_port_v2.port_1.id
  }

  connection {
    user        = "root"
    host        = openstack_networking_port_v2.port_1.fixed_ip.0.ip_address
    private_key = "~/path/to/key"
  }

  provisioner "remote-exec" {
    inline = [
      "echo terraform executed > /tmp/foo",
    ]
  }
}

Instances and Networks

Instances almost always require a network. Here are some notes to be aware of with how Instances and Networks relate:

* openstack_compute_instance_v2.instance: Error creating OpenStack server:
Expected HTTP response code [201 202] when accessing [POST https://example.com:8774/v2.1/servers], but got 409 instead
{"conflictingRequest": {"message": "Multiple possible networks found, use a Network ID to be more specific.", "code": 409}}

Importing instances

Importing instances can be tricky, since the nova api does not offer all information provided at creation time for later retrieval. Network interface attachment order, and number and sizes of ephemeral disks are examples of this.

Importing basic instance

Assume you want to import an instance with one ephemeral root disk, and one network interface.

Your configuration would look like the following:

resource "openstack_compute_instance_v2" "basic_instance" {
  name            = "basic"
  flavor_id       = "<flavor_id>"
  key_pair        = "<keyname>"
  security_groups = ["default"]
  image_id =  "<image_id>"

  network {
    name = "<network_name>"
  }
}

Then you execute

terraform import openstack_compute_instance_v2.basic_instance instance_id

Importing an instance with multiple emphemeral disks

The importer cannot read the emphemeral disk configuration of an instance, so just specify image_id as in the configuration of the basic instance example.

Importing instance with multiple network interfaces.

Nova returns the network interfaces grouped by network, thus not in creation order. That means that if you have multiple network interfaces you must take care of the order of networks in your configuration.

As example we want to import an instance with one ephemeral root disk, and 3 network interfaces.

Examples

resource "openstack_compute_instance_v2" "boot-from-volume" {
  name            = "boot-from-volume"
  flavor_id       = "<flavor_id"
  key_pair        = "<keyname>"
  image_id        = "<image_id>"
  security_groups = ["default"]

  network {
    name = "<network1>"
  }
  network {
    name = "<network2>"
  }
  network {
    name = "<network1>"
    fixed_ip_v4 = "<fixed_ip_v4>"
  }

}

In the above configuration the networks are out of order compared to what nova and thus the import code returns, which means the plan will not be empty after import.

So either with care check the plan and modify configuration, or read the network order in the state file after import and modify your configuration accordingly.

Importing instances with multiple block storage volumes.

We have an instance with two block storage volumes, one bootable and one non-bootable. Note that we only configure the bootable device as block_device. The other volumes can be specified as openstack_blockstorage_volume_v3

resource "openstack_compute_instance_v2" "instance_2" {
  name            = "instance_2"
  image_id        = "<image_id>"
  flavor_id       = "<flavor_id>"
  key_pair        = "<keyname>"
  security_groups = ["default"]

  block_device {
    uuid                  = "<image_id>"
    source_type           = "image"
    destination_type      = "volume"
    boot_index            = 0
    delete_on_termination = true
  }

   network {
    name = "<network_name>"
  }
}
resource "openstack_blockstorage_volume_v3" "volume_1" {
  size = 1
  name = "<vol_name>"
}
resource "openstack_compute_volume_attach_v2" "va_1" {
  volume_id   = openstack_blockstorage_volume_v3.volume_1.id
  instance_id = openstack_compute_instance_v2.instance_2.id
}

To import the instance outlined in the above configuration do the following:

terraform import openstack_compute_instance_v2.instance_2 instance_id
import openstack_blockstorage_volume_v3.volume_1 volume_id
terraform import openstack_compute_volume_attach_v2.va_1
instance_id/volume_id