vSphere RBVMomi REST interface, POC
Ok, I hear it from many webdev now, Ruby is easy, Ruby is great, Ruby is … ect :)
I found myself bound to Ruby, because the only descent library (not over-complicated) I could find to connect to a VMWare vSphere server was RBVMomi.
This is just nice, now I want to learn Ruby but… It’s just too bad if you want a simple interface for another language/platform.
Since HTTP is a widely used protocol, I decided to implement a REST bridge between rbvmomi and any other applications I could use.
RBVMomi being in ruby, I decided to use the Sinatra framework.
So far, I just started learning it, and I’m really happy with ruby. That piece of code says it all. I got a POC done quickly and it’s working just awesome for my use :)
The code
rbvmomi-server.rb
# File rbvmomi-server.rb
require 'sinatra'
require 'rbvmomi'
require 'json'
require 'iniparse'
require 'singleton'
require 'redis'
#
# Persistent API server. Lifetime is process lifetime
# Implementing redis as queue storage makes it multithread and restart safe
#
class APIServer
include Singleton
#internal : singletone init:
def initialize
@config = IniParse.parse( File.read('config.ini') )
@redis = Redis.new(@config['redis'])
@vim = RbVmomi::VIM.connect(:host => @config['vsphere']['host'], :user => @config['vsphere']['user'],
:password=> @config['vsphere']['password'], :insecure => @config['vsphere']['insecure'])
@dc = @vim.serviceInstance.find_datacenter(@config['vsphere']['datacenter'])
end
#internal : jobqueue
def getjob(jobid)
return JSON.parse(@redis.get(jobid))
end
def setjob(jobid,data)
return @redis.set(jobid, data.to_json)
end
#API functions :
def _api_getdatastoreinfo(params)
output = Array.new
paths = %w(name info.url summary.accessible summary.capacity summary.freeSpace)
propSet = [{ :type => 'Datastore', :pathSet => paths }]
filterSpec = { :objectSet => @dc.datastore.map { |ds| { :obj => ds } }, :propSet => propSet }
data = @vim.propertyCollector.RetrieveProperties(:specSet => [filterSpec])
data.select { |d| d['summary.accessible'] }.sort_by { |d| d['name'] }.each do |d|
size = d['summary.capacity']
free = d['summary.freeSpace']
used = size - free
pct_used = used*100.0/size
if d['name'].match('pcc-')
output << {'url' => d['info.url'], 'size' => size, 'used' => used, 'free' => free, 'percent' => pct_used, 'name' => d['name']}
end
end
return output
end
def _api_getjob(params)
return getjob(params['jobid'])
end
def _api_setjob(params)
return setjob(params['jobid'],params['data'])
end
end
get '/api/*' do |method|
APIServer.instance.method(['_api_' , method].join()).call(@params).to_json
end
config.ini
[vsphere]
hostname = xxxx
user = xxxx
password = xxxx
insecure = xxxx
datacenter = xxxx
[redis]
path = /var/run/redis.sock
---or----
host = xxxxx
port = xxxxx
Testing
We start the server :
$ ruby -rubygems rbvmomi-server.rb
[2012-04-29 14:41:23] INFO WEBrick 1.3.1
[2012-04-29 14:41:23] INFO ruby 1.8.7 (2011-06-30) [x86_64-linux]
== Sinatra/1.3.2 has taken the stage on 4567 for development with backup from WEBrick
[2012-04-29 14:41:23] INFO WEBrick::HTTPServer#start: pid=18829 port=4567
And we test ! :
$ curl "http://localhost:1234/api/getdatastoreinfo"
[{"percent":64.4684278916377,"used":188676997120,"free":103988736000,"size":292665733120,"name":"xxx","url":"netfs://3xxxxx/main/"},{"percent":60.7995903847724,"used":178150768640,"free":114862338048,"size":293013106688,"name":"xxx","url":"netfs://2xxx/main/"},{"percent":17.0715763111187,"used":49474035712,"free":240329523200,"size":289803558912,"name":"xxx","url":"netfs://1xxx/main/"}]
$
Yeaah
Running getjob/setjob
Sorry for my poor Ruby skills, I’m new at it.