Monthly Archives: March 2012

Nilgiri: managing cloud is now easier

I am working on this Nilgiri project lately aiming to provide a flexible environment of managing private cloud or hybrid cloud to the end users as well as for the sysadmins to make managing cloud simpler than ever. So, someone doesn’t need a tech-expert just to run an instance or to take a snapshot for later use or may be an user want to change his server’s security group at this very moment and he doesn’t have to wait for the system admin to response.

My aim is to make a full featured web console for Eucalyptus cloud ecosystem and as Eucalyptus follows the AWS standard so eventually it will work on AWS too. Why choose Eucalyptus as a platform? Well, currently Amazon is the most widely used cloud service provider in the world and also AWS has become the De-facto standard for cloud APIs. Though Openstack was following the same APIs in the beginning but it seems that gradually they are moving towards Rackspace’s API standards. So, here I am targeting the mass of cloud users at this moment who are currently using AWS, perhaps at some point they will want a private cloud may be because of security, governance or for any other reason. Another possible scenario would be people who are using Eucalyptus on their own and want to share some resources or may be workloads with AWS or may be they want to have both. This tool can be helpful for both type of users.

Nilgiri Dashboard

Nilgiri Dashboard

Euca2ools is a fantastic piece of command line software like Amazon EC2 API Tool created by the eucalyptus enthusiasts and employees. And probably this is the only piece of software which includes all the features of Eucalyptus. But Amazon has got the webconsole that Eucalyptus didn’t have until now. There are few more propitiatory/shareware/open source are also there for a while and some of them are browser plugins. But the usage and the freedom is often limited.

Available Imgaes

Available Imgaes

Create/Edit/Delete Groups

Create/Edit/Delete Groups

Nilgiri back-end is Python powered, I used Boto, a python library for AWS, and here is the benefit of using a De-facto standard APIs, because it works perfectly with Eucalyptus too. There are few changes in the latest AWS APIs, but the legacy version APIs of the library are also there, sometimes with “_deprecated” tags, so it works fine with Eucalyptus 2.x.

I’ve used Django as the web framework. Well, no hard reason why didn’t choose web2py or Grok or any other out there. HTML5 has been used to develop the whole application with Twitter’s booming Bootstrap. And a cloud management tool wouldn’t be complete without ajax. For javascript, popular jQuery is heavily used in Nilgiri.

The project is under rapid development and current codes is located here on Github.

For any suggestion or issues please use Github Issues.

Update:

jquery AJAX with Django

For my current project I am working on Django. But implementing ajax was little uncomfortable for me in the first place.

I wanted to use POST method but in Django there is a Cross Site Request Forgery protection(csrf) which don’t allow developers to implement it directly. The csrf protection also protect the PUT and DELETE.

So to enable the protection and work with those methods we need to go through certain steps. For forms the steps is pretty much simple, just add this {% csrf_token %} after <form>.

But to use it with jquery and ajax it’s little different. At first I tried to implement $.post() as it wasn’t working because of csrf error, I added a .js file and I was happy with it (btw, I was using Firefox until then). but then when I tried to view the application on Google Chrome it was showing our very known HTTP 403 error. And a little tracing lead me to some more detail.

jQuery.ajaxTransport.sendjquery.js:8088
jQuery.extend.ajaxjquery.js:7566
jQuery.each.jQuery.(anonymous function)jquery.js:7092
(anonymous function):8000/:198
jQuery.Callbacks.firejquery.js:1032
jQuery.Callbacks.self.fireWithjquery.js:1150
jQuery.extend.readyjquery.js:421
DOMContentLoaded

Little more reading lead me to some real fix. For ajax call, instead of using $.post() I just had to use $.ajax() and set an additional parameter.

$.ajax({
    url: "/test/test_method",
    success: function(data) {
        ...do something..
    },
    crossDomain: false
});

So basically the above code sends a GET request by default, but I was trying to use POST method. So I used the ajax csrf script from Django doc. This script sets a custom X-CSRFToken header to the value of the CSRF token on each XMLHttpRequest.

jQuery(document).ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    function sameOrigin(url) {
        // url could be relative or scheme relative or absolute
        var host = document.location.host; // host + port
        var protocol = document.location.protocol;
        var sr_origin = '//' + host;
        var origin = protocol + sr_origin;
        // Allow absolute or scheme relative URLs to same origin
        return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
            // or any other URL that isn't scheme relative or absolute i.e relative.
            !(/^(\/\/|http:|https:).*/.test(url));
    }
    function safeMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }

    if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});

add these three MIDDLEWARE_CLASSES

'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.csrf.CsrfResponseMiddleware',

and tada!!! it’s working on all the browsers.