Ansible’s cloud modules for OpenStack offer various modules to manage most of OpenStack’s components. In this post, we will show how to perform basic operations with Cinder volumes — create a volume, attach it to and detach it from a VM.
In order to be able to follow the steps and perform the commands presented in this post, you need to do the following:
- Install Ansible (
$ sudo pip install ansible),
- Install Shade (
$ pip install shade).
- Deploy two Ubuntu 16.04 VMs. They will be referred to as
vm2. You can deploy a VM in Dashboard (Compute -> Instances -> Launch Instance) .
- Set the
OS_REGION_NAME) to enable Absible the access to your project. The easiest way to do so is to source the openrc file. You can download one in Dashboard -> Access & Security -> API Access -> Download OpenStack RC File v3 and execute it (run
$ source ./your-project-openrc.sh).
- Finally, have one of the SSH keys available in the project to be added to your SSH agent so that you as well as Ansible can SSH to the VMs.
We assume that you have at least a basic knowledge of Ansible. Otherwise, we recommend reading this tutorial first.
Cinder provides block storage for OpenStack compute instances. It is designated for providing persistent storage that is independent on the life-cycle of compute instances. That means that we are able to reuse a Cinder volume on several instances (only one at a time). Therefore, the tasks concerning block storage include mainly the creation and deletion of volumes and attachment of volumes to and detachment from an instance.
Create a Cinder volume
Creation of volumes is usually not performed as frequently as its attachment because volumes are often being reused for multiple instances as a form of data persistence over multiple instances’ life-cycles. Nevertheless, it is also important to be able to automate this step as a part of creation of an environment ‘from the scratch’.
The module for creation and deletion of a volume is called
os_volume. There, we can specify the name, size, and other parameters of the volume we want to create. In our case we specify a 1GB volume called
ansible_volume in the availability zone
nova . Let’s attach the volume to the VM in playbook called create_volume.yaml.
- name: Create persistent data storage hosts: localhost tasks: - name: Create 1GB volume os_volume: state: present display_name: ansible_volume size: 1 availability_zone: nova display_description: Test volume created by Ansible.
And execute the playbook — Ansible will use the environment variables to perform the operation in the specified project and by the specified user.
$ ansible-playbook create_volume.yaml
Once the command is finished, you can check the Dashboard to see that the volume is present (Compute -> Volumes).
Attach the volume to a VM
Having an existing volume and a running VM in place, we can attach the volume to the VM so that it can be used by the running instance. Since the volume has just been created, it contains no data yet. Let’s attach the volume to the VM in playbook called attach_volume_vm1.yaml.
- name: Attach a volume hosts: localhost tasks: - name: Atach the volume to vm1 os_server_volume: state: present server: vm1 volume: ansible_volume device: /dev/vdb
For the volume attachment, we use the module
os_server_volume. The module requires, as expected, the name of the interacting VM (parameter
server) as well as the volume. Besides, a useful option is specifying the device to attach the volume to. In our case, we chose /dev/vdb. Before choosing the device, make sure that it is free. Should you omit this parameter, the device name is determined automatically.
Execute the playbook the usual way:
$ ansible-playbook attach_volume_vm1.yaml
You can make sure again in the Dashboard that the volume is attached to the VM (Dashboard -> Volumes).
Mount the attached volume
Now let’s mount the volume on the VM. Since we specified the path to attach the volume to, we can use that for the volume mounting. To do so, let’s SSH to the VM and switch to superuser.
localhost$ ssh ubuntu@<IP_of_vm1> vm1$ sudo -i
Having the volume attached to the VM, we will build a file system on the volume so that it can be browsed in the same way as the file system on the VM. For that, we will use mkfs.ext4 to create file system ext4.
# mkfs.ext4 /dev/vdb
The file system, after being created, can be mounted. To mount a file system, we need to specify the device path, the path to mount the file system to, and the file system type. We will mount the file system to /tmp/volume. Since the folder does not exist yet, we will create it before mounting the volume.
# mkdir -p /tmp/volume # mount /dev/vdb /tmp/volume/ -t ext4
The filesystem is now mounted to the specified path so we can create a file there. The file is being created on the volume so that even if the VM gets terminated, we will not lose the content.
# echo "Test file on the mounted volume." >> /tmp/volume/test_file.txt
You can exit the SSH connection now.
Detach a volume
The current state is us having the volume attached to
vm1. Moreover, the volume has a file system and there is a text file that we created there. To use the volume (with its content) on another VM, let’s detach the volume with ansible first. To do so, we specify the playbook detach_volume_vm1.yaml. The playbook uses the same module as the one for volume attachment —
os_server_volume — however this time with
state parameter set to
absent. That indicates that we do not want to have the specified state. The rest of the module parameters specify the volume that we manipulate in the same way as in attach_volume_vm1.yaml.
- name: Detach a volume hosts: localhost tasks: - name: Detach the volume from vm1 os_server_volume: state: absent server: vm1 volume: ansible_volume
The playbook can be executed now.
$ ansible-playbook detach_volume_vm1.yaml
See the result
The volume is no longer attached to the first VM. Therefore, we can attach it to the second one. To do so, we need to slightly modify the playbook attach_volume_vm1.yaml. The parameter
server needs to be changed from
vm2 so that the volume will be attached to
vm2 instead. Save the modified playbook as attach_volume_vm2.yaml and execute it.
$ ansible-playbook attach_volume_vm2.yaml
The volume is now attached to the second VM. You can again check it in the Dashboard. Now, we use the same approach as before to mount the volume. First, establish the SSH connection to vm2, then switch to supersuer, create a folder for mounting the volume, and perform the mount (we do not need to execute mkfs since the file system has already been created the first time we used the volume and is still present).
$ ssh ubuntu@<IP_of_vm2> $ sudo -i # mkdir -p /tmp/volume # mount /dev/vdb /tmp/volume/ -t ext4
The volume is now mounted to /tmp/volume — as before. Since the volume provides persistent storage, the content we created on the first VM should be now available on
vm2. Let’s try to read the file /tmp/volume/test_file.txt
# cat /tmp/volume/test_file.txt Test file on the mounted volume.
Ansible is a useful tool for operating with OpenStack infrastructure. In this article, we used Ansible to operate an instance of OpenStack Block Storage. It provided persistent storage for VMs. We created the volume and attached it to and later detached it from a VM with use of Ansible modules and playbooks.
Ansible is an easy way of how to transfer your basic operations with OpenStack infrastructure into code. That helps when redeploying a certain setting. It shortens the necessary time and can assure the same state every time it is used. Considering Cinder, we showed how it eases volume creations and its presence on preferred VM.