IBM Support

Create a virtual machine in IBM Cloud Infrastruture Center by Terraform

How To


Summary

IBM Cloud Infrastructure Center supports to create infrastructures by Terraform®.
This guide is to describe how to create a virtual machine instance in IBM Cloud Infrastructure Center by Terraform®.

Objective

About the examples given in this article, users can learn how to create virtual machines in IBM Cloud Infrastructure Center by Terraform®.
These examples also contain CoreOS specific resource configuration statements, so CoreOS users know the required resource configuration when you create a virtual machine.

Steps

Install Terraform® and terraform-provider-openstack on your machine

For different machine's architecture, there are two methods to prepare the environment:
  • If your machine's architecture is x86, you just need to install Terraform®.
  • If your machine's architecture is s390x, first, you need to install Terraform®; Second, you need to build terraform-provider-openstack manually, then move it to the directory “~/.terraform.d/plugins“.

Prepare your Terraform® configuration files

Each Terraform® project needs a separate working directory, so you should create a new directory for your project. Under this directory, all files ended with *.tf are loaded by Terraform®
The *.tf files are Terraform® configuration files, let's call it main.tf as an example
There are two examples to display the main.tf‘ contents.
  • Basic instance with creating image, the contents of its main.tf are as follows:
  # here, we use openstack as the provider
provider "openstack" {
  user_name  = "self-service-test1"
  password    = "******"
  tenant_name = "ibm-default"
  auth_url = "https://192.168.0.1/icic/openstack/identity/v3"
  domain_name = "default"
  insecure    = true
}
# create an image from file rhel77_ext4_new.img, please make sure that the attribute value of the image and
# the field value in the resource "openstack_images_image_v2" match correctly
resource "openstack_images_image_v2" "image_rhl_wxk"{
  name = "image_rhl_wxk"
  local_file_path = "/root/rhel77_ext4_new.img"
  container_format = "bare"
  disk_format      = "raw"
  properties = {
    os_distro = "Rhel7"
    architecture = "s390x"
    disk_type = "DASD"
  }
}
# use new image, and existing flavor, network to create a rhl instance
resource "openstack_compute_instance_v2" "instance_rhl_wxk" {
  name      = "instance_rhl_wxk"
  image_id  = "${openstack_images_image_v2.image_rhl_wxk.id}"
  flavor_id = "3034ac73-2899-49ab-aa15-430f1fa09aa8"
  network {
    name = "flat01"
  }
}
 Notes for this case:
  1. The "provider" here used is "openstack", the product IBM Cloud Infrastructure Center is compatible with OpenStack®, so IBM Cloud Infrastructure Center supports to create infrastructures by Terraform®, and Terraform® configurations and resource files are the same as OpenStack®.
  2. In this case's provider's fields, the user "self-service-test1" is the self-service user. IBM Cloud Infrastructure Center supports that use self-service user to create instances. 
  3. For the detailed explanation of the provider's fields, go to https://www.terraform.io/docs/providers/openstack/index.html#configuration-reference can see the specific description.
  4. When you use the existing image, flavor, network in resource "openstack_compute_instance_v2" 's fields,  get its correct name or ID. If you want to create them by Terraform®, refer to https://www.terraform.io/docs/providers/openstack/r/images_image_v2.html for details.
  5. For the details of resource "openstack_compute_instance_v2", https://www.terraform.io/docs/providers/openstack/r/compute_instance_v2.html#argument-reference has the specific explanation for it.
  • Boot from volume with RHCOS image, the contents of its main.tf are as follows:
  provider "openstack" {
  user_name   = "project-admin-test1"
  password    = "******"
  tenant_name = "ibm-default"
  auth_url = "https://192.168.0.1/icic/openstack/identity/v3"
  domain_name = "default"
  insecure    = true
}
variable "container_name"{
  type = "string"
  default = "tf-test-container-1"
}
variable "object_name"{
  type = "string"
  default = "obj-ign"
}
variable "complete_url"{
  type = "string"
  default = "https://192.168.0.1:8080/v1/AUTH_a28db3fc01964918906d525d4eaa9f93/tf-test-container-1/obj-ign"
}
resource "openstack_objectstorage_container_v1" "container_wxk" {
  name   = "${var.container_name}"
  container_read = ".r:*"
}
resource "openstack_objectstorage_object_v1" "doc_wxk" {
  container_name = "${openstack_objectstorage_container_v1.container_wxk.name}"
  name = "${var.object_name}"
  content_type = "application/json"
  source       = "/root/xinke/cic-test/coreos/config.ign"
}
resource "openstack_compute_instance_v2" "boot-from-volume" {
  name            = "boot-from-volume"
  flavor_id = "547b553f-c14c-4ea5-92be-9a075e43ee3f" 
  block_device {
    uuid                  = "1b0b8f39-90b7-49a2-a80a-88b31bf6e1dd"
# this uuid here means image id, the image is rhcos scsi image
    source_type           = "image"
    volume_size           = 30
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
# for rhcos, delete_on_termination must be true, or it will fail to create instance
  }
  network {
    name = "flat01"
  }
  user_data = "${base64encode(var.complete_url)}"
}
In this case, there are some points you need to know:
  1. The user "project-admin-test1" means project admin. It has permission to access resources under this project.
  2. When you boot from volume, you need to add block_device to resource "openstack_compute_instance_v2".
  3. For the resource "openstack_objectstorage_container_v1", you must set container_read = ".r:*".
  4. For RHCOS, delete_on_termination's value is true. The reason is that RHCOS volume contains RHCOS-specific information (ignition), it cannot be reused by other instances. It is failed to create RHCOS instance when delete_on_termination is set false.
  5. For RHCOS, you must add user_data = "${base64encode(var.complete_url)}" to resource "openstack_compute_instance_v2", and the user_data's value is the ignition's URL with base64 format.
  • The "variable" are only variables used to make up a URL with ignition. Make sure to use the same variable name throughout all main.tf, for example, <container_name>, <object_name>, <complete_url>
  • The variable "complete_url" is to store the ignition file. It has the following format:

The steps to create instance by Terraform®

There is the main step to create an instance by Terraform®
  • Create and enter a directory named "terraform-cic"
  • Put main.tf file to directory "terraform-cic"
  • Run terraform init
    • When you use Terraform® for the first time, this command must be executed. It initializes the workspace and finds your providers' plug-ins. If it could find available plug-ins (for example: terraform-provider-openstack), it downloads them automatically. If it can't find the correct architecture's available plug-ins, build and move it to the correct directory manually.
  [root@hostname scsi]# terraform init
Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "openstack" (1.28.0)...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.openstack: version = "~> 1.28"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
  • Run terraform apply
    • This command will execute creating action, you can see your instance on UI after you finish it.
  [root@hostname scsi]# terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:
  + openstack_compute_instance_v2.boot-from-volume
      id:                                   <computed>
      access_ip_v4:                         <computed>
      access_ip_v6:                         <computed>
      all_metadata.%:                       <computed>
      all_tags.#:                           <computed>
      availability_zone:                    <computed>
      block_device.#:                       "1"
      block_device.0.boot_index:            "0"
      block_device.0.delete_on_termination: "false"
      block_device.0.destination_type:      "volume"
      block_device.0.source_type:           "image"
      block_device.0.uuid:                  "1b0b8f39-90b7-49a2-a80a-88b31bf6e1dd"
      block_device.0.volume_size:           "30"
      flavor_id:                            "547b553f-c14c-4ea5-92be-9a075e43ee3f"
      flavor_name:                          <computed>
      force_delete:                         "false"
      image_id:                             <computed>
      image_name:                           <computed>
      name:                                 "boot-from-volume"
      network.#:                            "1"
      network.0.access_network:             "false"
      network.0.fixed_ip_v4:                <computed>
      network.0.fixed_ip_v6:                <computed>
      network.0.floating_ip:                <computed>
      network.0.mac:                        <computed>
      network.0.name:                       "flat01"
      network.0.port:                       <computed>
      network.0.uuid:                       <computed>
      power_state:                          "active"
      region:                               <computed>
      security_groups.#:                    <computed>
      stop_before_destroy:                  "false"
      user_data:                            "4d88996b2f62cdaf911906931b5aa24740f55749"
  + openstack_objectstorage_container_v1.container_wxk
      id:                                   <computed>
      container_read:                       ".r:*"
      force_destroy:                        "false"
      name:                                 "tf-test-container-1"
      region:                               <computed>
  + openstack_objectstorage_object_v1.doc_wxk
      id:                                   <computed>
      container_name:                       "tf-test-container-1"
      content_disposition:                  <computed>
      content_encoding:                     <computed>
      content_length:                       <computed>
      content_type:                         "application/json"
      date:                                 <computed>
      delete_at:                            <computed>
      detect_content_type:                  "false"
      etag:                                 <computed>
      last_modified:                        <computed>
      name:                                 "obj-ign"
      object_manifest:                      <computed>
      region:                               <computed>
      source:                               "/root/xinke/cic-test/coreos/config.ign"
      trans_id:                             <computed>
Plan: 3 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.
  Enter a value: yes
openstack_objectstorage_container_v1.container_wxk: Creating...
  container_read: "" => ".r:*"
  force_destroy:  "" => "false"
  name:           "" => "tf-test-container-1"
  region:         "" => "<computed>"
openstack_compute_instance_v2.boot-from-volume: Creating...
  access_ip_v4:                         "" => "<computed>"
  access_ip_v6:                         "" => "<computed>"
  all_metadata.%:                       "" => "<computed>"
  all_tags.#:                           "" => "<computed>"
  availability_zone:                    "" => "<computed>"
  block_device.#:                       "" => "1"
  block_device.0.boot_index:            "" => "0"
  block_device.0.delete_on_termination: "" => "false"
  block_device.0.destination_type:      "" => "volume"
  block_device.0.source_type:           "" => "image"
  block_device.0.uuid:                  "" => "1b0b8f39-90b7-49a2-a80a-88b31bf6e1dd"
  block_device.0.volume_size:           "" => "30"
  flavor_id:                            "" => "547b553f-c14c-4ea5-92be-9a075e43ee3f"
  flavor_name:                          "" => "<computed>"
  force_delete:                         "" => "false"
  image_id:                             "" => "<computed>"
  image_name:                           "" => "<computed>"
  name:                                 "" => "boot-from-volume"
  network.#:                            "" => "1"
  network.0.access_network:             "" => "false"
  network.0.fixed_ip_v4:                "" => "<computed>"
  network.0.fixed_ip_v6:                "" => "<computed>"
  network.0.floating_ip:                "" => "<computed>"
  network.0.mac:                        "" => "<computed>"
  network.0.name:                       "" => "flat01"
  network.0.port:                       "" => "<computed>"
  network.0.uuid:                       "" => "<computed>"
  power_state:                          "" => "active"
  region:                               "" => "<computed>"
  security_groups.#:                    "" => "<computed>"
  stop_before_destroy:                  "" => "false"
  user_data:                            "" => "4d88996b2f62cdaf911906931b5aa24740f55749"
openstack_objectstorage_container_v1.container_wxk: Creation complete after 8s (ID: tf-test-container-1)
openstack_objectstorage_object_v1.doc_wxk: Creating...
  container_name:      "" => "tf-test-container-1"
  content_disposition: "" => "<computed>"
  content_encoding:    "" => "<computed>"
  content_length:      "" => "<computed>"
  content_type:        "" => "application/json"
  date:                "" => "<computed>"
  delete_at:           "" => "<computed>"
  detect_content_type: "" => "false"
  etag:                "" => "<computed>"
  last_modified:       "" => "<computed>"
  name:                "" => "obj-ign"
  object_manifest:     "" => "<computed>"
  region:              "" => "<computed>"
  source:              "" => "/root/xinke/cic-test/coreos/config.ign"
  trans_id:            "" => "<computed>"
openstack_objectstorage_object_v1.doc_wxk: Creation complete after 2s (ID: tf-test-container-1/obj-ign)
openstack_compute_instance_v2.boot-from-volume: Still creating... (10s elapsed)
.......
openstack_compute_instance_v2.boot-from-volume: Still creating... (2m40s elapsed)
openstack_compute_instance_v2.boot-from-volume: Creation complete after 2m42s (ID: 5cf27d65-ec81-44d1-bd58-bc1531540720)
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
You can see your instance on UI.
  • Run terraform destroy
    • This command deletes all the resources included in main.tf file.

Document Location

Worldwide

[{"Business Unit":{"code":"BU054","label":"Systems w\/TPS"},"Product":{"code":"SSLL2F","label":"IBM Cloud Infrastructure Center"},"ARM Category":[{"code":"a8m0z0000001iPmAAI","label":"Chatbot Used"}],"ARM Case Number":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"1.1.1","Line of Business":{"code":"LOB16","label":"Mainframe HW"}}]

Document Information

Modified date:
05 November 2020

UID

ibm16237790