Saturday, September 13, 2014

Automate Rackspace Cloud Block Storage volume creation with Ansible

Today I want to automate Rackspace Cloud Block Storage volume creation with Ansible for Rackspace instances.

To do that, we will need rax modules that requires to install pyrax.

After pyrax is installed, then I tested to create a block storage volume with the module rax_cbs
and that thrown out an error:
msg: pyrax is required for this module

That's interesting. I checked the python path and tested pyrax:

$ which python
/usr/local/bin/python

 $ python
Python 2.7.7 (default, Jun 18 2014, 16:33:32)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyrax
>>>

Checked the ansible python path
$ head /usr/local/bin/ansible
#!/usr/local/opt/python/bin/python2.7

Found both python and /usr/local/opt/python/bin/python2.7 are symbolic links of /usr/local/Cellar/python/2.7.7_2/Frameworks/Python.framework/Versions/2.7/bin/python2.7.

Google around but can't find the answer.

Finally verified the module rax_cbs:
$ head /usr/share/ansible/cloud/rax_cbs
#!/usr/bin/python

Then:
$ /usr/bin/python
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyrax
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named pyrax

That's why it didn't work! /usr/bin/python is built-in python on Mac OS X while 2.7.7 was installed via Homebrew to different path.

So let's set the ansible_python_interpreter for localhost that is used by rax modules in the ansible/hosts file:
[local]
localhost ansible_connection=local ansible_python_interpreter=/usr/local/opt/python/bin/python2.7

But then got another error:
msg: No CloudBlockStorageVolume matching

Found the answer to patch the /usr/share/ansible/cloud/rax_cbs

Voila!

I also want to attach the volume to the instance, then fdisk/create partition/format/mount it automatically.., so we have to check if the device already exist or not, if not then create/attach a Cloud Block Storage volume and fdisk/create partition/format..

Below is the playbook.

Note that this playbook will be executed for remote Rackspace instances so we don't need to set hosts/connection for Rackspace build/attach block storage volume tasks as the example when the local_action module already delegates to the localhost defined in ansible/hosts automatically.

 # file:Rackspace_disk/tasks/main.yml  
 - name: Check if device /dev/xvd_ present  
  shell: fdisk -l | grep 'Disk {{device}}' | wc -l  
  changed_when: False  
  register: device_present  
 - name: Build a Block Storage Volume  
  local_action:  
   module: rax_cbs  
   credentials: "{{credentials}}"  
   name: "{{volum_name}}"  
   volume_type: "{{volum_type}}"  
   size: "{{volum_size}}"  
   region: "{{region}}"   
   wait: yes  
   state: present  
   meta:  
    app: "{{volum_name}}"  
  sudo: no  
  when: device_present.stdout is defined and device_present.stdout|int == 0  
 - name: Attach a Block Storage Volume  
  local_action:  
   module: rax_cbs_attachments  
   credentials: "{{credentials}}"  
   volume: "{{volum_name}}"  
   server: "{{server}}"  
   device: "{{device}}" #/dev/xvd_  
   region: "{{region}}"  
   wait: yes  
   state: present  
  sudo: no  
  when: device_present.stdout is defined and device_present.stdout|int == 0  
 - name: Check if partition /dev/xvd_1 present  
  shell: fdisk -l | grep {{device}}1 | wc -l  
  changed_when: False  
  register: partition_present  
 - name: Fdisk / create partition / format  
  shell: "echo -e 'n\np\n1\n\n\nw\n' | fdisk {{device}} && mkfs -t {{fstype}} {{device}}1 && tune2fs -m 0 {{device}}1 "  
  when: partition_present.stdout is defined and partition_present.stdout|int == 0  
 - file: path={{mount_dir}} state=directory  
 - name: Mount device  
  mount: name={{mount_dir}} src={{device}}1 fstype={{fstype}} opts='defaults,noatime,nofail' state=mounted  




 



2 comments:

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete