Allow pool 'alias' names

The following pool configuration would allow a pool to be aliased in POST
requests as 'centos-6-x86_64', 'centos-6-amd64', or 'centos-6-64':

````yaml
- name: 'centos-6-x86_64'
  alias: [ 'centos-6-amd64', 'centos-6-64' ]
  template: 'templates/centos-6-x86_64'
  folder: 'vmpooler/centos-6-x86_64'
  datastore: 'instance1'
  size: 5
````

The 'alias' configuration can be either a string or an array.

Note that even when requesting an alias, the pool's 'name' is returned in
the JSON response:

````
$ curl -d '{"centos-6-64":"1"}' --url vmpooler/api/v1/vm
````
````json
{
  "ok": true,
  "centos-6-x86_64": {
    "hostname": "cuna2qeahwlzji7"
  },
  "domain": "company.com"
}
````
This commit is contained in:
Scott Schneider 2015-11-04 19:31:32 -08:00
parent 12da1e07d2
commit 17b24d69ad
3 changed files with 95 additions and 81 deletions

View file

@ -33,6 +33,20 @@ module Vmpooler
parsed_config[:config]['vm_checktime'] ||= 15 parsed_config[:config]['vm_checktime'] ||= 15
parsed_config[:config]['vm_lifetime'] ||= 24 parsed_config[:config]['vm_lifetime'] ||= 24
# Create an index of pool aliases
parsed_config[:pools].each do |pool|
if pool['alias']
if pool['alias'].kind_of?(Array)
pool['alias'].each do |a|
parsed_config[:alias] ||= {}
parsed_config[:alias][a] = pool['name']
end
elsif pool['alias'].kind_of?(String)
parsed_config[:alias][pool['alias']] = pool['name']
end
end
end
if parsed_config[:graphite]['server'] if parsed_config[:graphite]['server']
parsed_config[:graphite]['prefix'] ||= 'vmpooler' parsed_config[:graphite]['prefix'] ||= 'vmpooler'
end end

View file

@ -28,6 +28,60 @@ module Vmpooler
validate_token(backend) validate_token(backend)
end end
def alias_deref(hash)
newhash = {}
hash.each do |key, val|
if backend.exists('vmpooler__ready__' + key)
newhash[key] = val
else
if Vmpooler::API.settings.config[:alias][key]
newkey = Vmpooler::API.settings.config[:alias][key]
newhash[newkey] = val
end
end
end
newhash
end
def checkout_vm(template, result)
vm = backend.spop('vmpooler__ready__' + template)
unless vm.nil?
backend.sadd('vmpooler__running__' + template, vm)
backend.hset('vmpooler__active__' + template, vm, Time.now)
backend.hset('vmpooler__vm__' + vm, 'checkout', Time.now)
if Vmpooler::API.settings.config[:auth] and has_token?
validate_token(backend)
backend.hset('vmpooler__vm__' + vm, 'token:token', request.env['HTTP_X_AUTH_TOKEN'])
backend.hset('vmpooler__vm__' + vm, 'token:user',
backend.hget('vmpooler__token__' + request.env['HTTP_X_AUTH_TOKEN'], 'user')
)
if config['vm_lifetime_auth'].to_i > 0
backend.hset('vmpooler__vm__' + vm, 'lifetime', config['vm_lifetime_auth'].to_i)
end
end
result[template] ||= {}
if result[template]['hostname']
result[template]['hostname'] = [result[template]['hostname']] unless result[template]['hostname'].is_a?(Array)
result[template]['hostname'].push(vm)
else
result[template]['hostname'] = vm
end
else
status 503
result['ok'] = false
end
result
end
get "#{api_prefix}/status/?" do get "#{api_prefix}/status/?" do
content_type :json content_type :json
@ -277,11 +331,15 @@ module Vmpooler
post "#{api_prefix}/vm/?" do post "#{api_prefix}/vm/?" do
content_type :json content_type :json
result = {} result = { 'ok' => false }
jdata = alias_deref(JSON.parse(request.body.read))
if not jdata.nil? and not jdata.empty?
available = 1 available = 1
else
jdata = JSON.parse(request.body.read) status 404
end
jdata.each do |key, val| jdata.each do |key, val|
if backend.scard('vmpooler__ready__' + key).to_i < val.to_i if backend.scard('vmpooler__ready__' + key).to_i < val.to_i
@ -293,46 +351,10 @@ module Vmpooler
result['ok'] = true result['ok'] = true
jdata.each do |key, val| jdata.each do |key, val|
result[key] ||= {}
val.to_i.times do |_i| val.to_i.times do |_i|
vm = backend.spop('vmpooler__ready__' + key) result = checkout_vm(key, result)
unless vm.nil?
backend.sadd('vmpooler__running__' + key, vm)
backend.hset('vmpooler__active__' + key, vm, Time.now)
backend.hset('vmpooler__vm__' + vm, 'checkout', Time.now)
if Vmpooler::API.settings.config[:auth] and has_token?
validate_token(backend)
backend.hset('vmpooler__vm__' + vm, 'token:token', request.env['HTTP_X_AUTH_TOKEN'])
backend.hset('vmpooler__vm__' + vm, 'token:user',
backend.hget('vmpooler__token__' + request.env['HTTP_X_AUTH_TOKEN'], 'user')
)
if config['vm_lifetime_auth'].to_i > 0
backend.hset('vmpooler__vm__' + vm, 'lifetime', config['vm_lifetime_auth'].to_i)
end end
end end
result[key] ||= {}
if result[key]['hostname']
result[key]['hostname'] = [result[key]['hostname']] unless result[key]['hostname'].is_a?(Array)
result[key]['hostname'].push(vm)
else
result[key]['hostname'] = vm
end
else
status 503
result['ok'] = false
end
end
end
else
status 503
result['ok'] = false
end end
if result['ok'] && config['domain'] if result['ok'] && config['domain']
@ -345,7 +367,7 @@ module Vmpooler
post "#{api_prefix}/vm/:template/?" do post "#{api_prefix}/vm/:template/?" do
content_type :json content_type :json
result = {} result = { 'ok' => false }
payload = {} payload = {}
params[:template].split('+').each do |template| params[:template].split('+').each do |template|
@ -353,10 +375,16 @@ module Vmpooler
payload[template] = payload[template] + 1 payload[template] = payload[template] + 1
end end
available = 1 payload = alias_deref(payload)
payload.keys.each do |template| if not payload.nil? and not payload.empty?
if backend.scard('vmpooler__ready__' + template) < payload[template] available = 1
else
status 404
end
payload.each do |key, val|
if backend.scard('vmpooler__ready__' + key).to_i < val.to_i
available = 0 available = 0
end end
end end
@ -364,45 +392,11 @@ module Vmpooler
if (available == 1) if (available == 1)
result['ok'] = true result['ok'] = true
params[:template].split('+').each do |template| payload.each do |key, val|
result[template] ||= {} val.to_i.times do |_i|
result = checkout_vm(key, result)
vm = backend.spop('vmpooler__ready__' + template)
unless vm.nil?
backend.sadd('vmpooler__running__' + template, vm)
backend.hset('vmpooler__active__' + template, vm, Time.now)
backend.hset('vmpooler__vm__' + vm, 'checkout', Time.now)
if Vmpooler::API.settings.config[:auth] and has_token?
validate_token(backend)
backend.hset('vmpooler__vm__' + vm, 'token:token', request.env['HTTP_X_AUTH_TOKEN'])
backend.hset('vmpooler__vm__' + vm, 'token:user',
backend.hget('vmpooler__token__' + request.env['HTTP_X_AUTH_TOKEN'], 'user')
)
if config['vm_lifetime_auth'].to_i > 0
backend.hset('vmpooler__vm__' + vm, 'lifetime', config['vm_lifetime_auth'].to_i)
end end
end end
result[template] ||= {}
if result[template]['hostname']
result[template]['hostname'] = [result[template]['hostname']] unless result[template]['hostname'].is_a?(Array)
result[template]['hostname'].push(vm)
else
result[template]['hostname'] = vm
end
else
status 503
result['ok'] = false
end
end
else
status 503
result['ok'] = false
end end
if result['ok'] && config['domain'] if result['ok'] && config['domain']

View file

@ -188,6 +188,10 @@
# The name of the pool. # The name of the pool.
# (required) # (required)
# #
# - alias
# Other names this pool can be requested as.
# (optional)
#
# - template # - template
# The template or virtual machine target to spawn clones from. # The template or virtual machine target to spawn clones from.
# (required) # (required)
@ -221,6 +225,7 @@
:pools: :pools:
- name: 'debian-7-i386' - name: 'debian-7-i386'
alias: [ 'debian-7-32' ]
template: 'Templates/debian-7-i386' template: 'Templates/debian-7-i386'
folder: 'Pooled VMs/debian-7-i386' folder: 'Pooled VMs/debian-7-i386'
datastore: 'vmstorage' datastore: 'vmstorage'
@ -228,6 +233,7 @@
timeout: 15 timeout: 15
ready_ttl: 1440 ready_ttl: 1440
- name: 'debian-7-x86_64' - name: 'debian-7-x86_64'
alias: [ 'debian-7-64', 'debian-7-amd64' ]
template: 'Templates/debian-7-x86_64' template: 'Templates/debian-7-x86_64'
folder: 'Pooled VMs/debian-7-x86_64' folder: 'Pooled VMs/debian-7-x86_64'
datastore: 'vmstorage' datastore: 'vmstorage'