From 8a22434629b8edffdb43e53ecff6af3c4bb81e67 Mon Sep 17 00:00:00 2001 From: Rick Sherman Date: Wed, 20 Jul 2016 17:11:35 -0500 Subject: [PATCH] (QENG-3376) Allow lifetime to be set per-pool At current vm_lifetime and vm_lifetime_auth are configured globally only. This change allows that value to be set/overridden per pool. --- lib/vmpooler/api/v1.rb | 12 +++--- spec/helpers.rb | 2 +- spec/vmpooler/api/v1/vm_spec.rb | 68 ++++++++++++++++++++++++++++++++- vmpooler.yaml.example | 10 +++++ 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/lib/vmpooler/api/v1.rb b/lib/vmpooler/api/v1.rb index 4bd9852..75dcd21 100644 --- a/lib/vmpooler/api/v1.rb +++ b/lib/vmpooler/api/v1.rb @@ -66,8 +66,9 @@ module Vmpooler 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) + pool_lifetime_auth = pools.find {|p| p["name"] == template }['vm_lifetime_auth'] + if (pool_lifetime_auth || config['vm_lifetime_auth']).to_i > 0 + backend.hset('vmpooler__vm__' + vm, 'lifetime', (pool_lifetime_auth || config['vm_lifetime_auth']).to_i) end end end @@ -455,13 +456,14 @@ module Vmpooler result[params[:hostname]] = {} result[params[:hostname]]['template'] = rdata['template'] - result[params[:hostname]]['lifetime'] = (rdata['lifetime'] || config['vm_lifetime']).to_i + pool_auth = pools.find {|p| p["name"] == rdata['template'] }['vm_lifetime'] + result[params[:hostname]]['lifetime'] = (rdata['lifetime'] || pool_auth || config['vm_lifetime']).to_i if rdata['destroy'] - result[params[:hostname]]['running'] = ((Time.parse(rdata['destroy']) - Time.parse(rdata['checkout'])) / 60 / 60).round(2) + result[params[:hostname]]['running'] = ((Time.parse(rdata['destroy']) - Time.parse(rdata['checkout'])) / 60 / 60).round(2).to_f result[params[:hostname]]['state'] = 'destroyed' elsif rdata['checkout'] - result[params[:hostname]]['running'] = ((Time.now - Time.parse(rdata['checkout'])) / 60 / 60).round(2) + result[params[:hostname]]['running'] = ((Time.now - Time.parse(rdata['checkout'])) / 60 / 60).round(2).to_f result[params[:hostname]]['state'] = 'running' elsif rdata['check'] result[params[:hostname]]['state'] = 'ready' diff --git a/spec/helpers.rb b/spec/helpers.rb index 292b9f4..7c4eb1a 100644 --- a/spec/helpers.rb +++ b/spec/helpers.rb @@ -36,7 +36,7 @@ def create_ready_vm(template, name, token = nil) create_vm(name, token) redis.sadd("vmpooler__ready__#{template}", name) # REMIND: should be __vm__? - redis.hset("vmpooler_vm_#{name}", "template", template) + redis.hset("vmpooler__vm__#{name}", "template", template) end def create_running_vm(template, name, token = nil) diff --git a/spec/vmpooler/api/v1/vm_spec.rb b/spec/vmpooler/api/v1/vm_spec.rb index 0c14561..3b86702 100644 --- a/spec/vmpooler/api/v1/vm_spec.rb +++ b/spec/vmpooler/api/v1/vm_spec.rb @@ -26,10 +26,11 @@ describe Vmpooler::API::V1 do config: { 'site_name' => 'test pooler', 'vm_lifetime_auth' => 2, + 'vm_lifetime' => 12, }, pools: [ {'name' => 'pool1', 'size' => 5}, - {'name' => 'pool2', 'size' => 10} + {'name' => 'pool2', 'size' => 10, 'vm_lifetime' => 1, 'vm_lifetime_auth' => 4} ], statsd: { 'prefix' => 'stats_prefix'}, alias: { 'poolone' => 'pool1' }, @@ -283,7 +284,29 @@ describe Vmpooler::API::V1 do end context '(auth configured)' do - it 'extends VM lifetime if auth token is provided' do + it 'extends VM lifetime to pool value if auth token is provided' do + app.settings.set :config, auth: true + + create_ready_vm 'pool2', 'qrstuvwxyz012345' + + post "#{prefix}/vm", '{"pool2":"1"}', { + 'HTTP_X_AUTH_TOKEN' => 'abcdefghijklmnopqrstuvwxyz012345' + } + expect_json(ok = true, http = 200) + + expected = { + ok: true, + pool2: { + hostname: 'qrstuvwxyz012345' + } + } + expect(last_response.body).to eq(JSON.pretty_generate(expected)) + + vm = fetch_vm('qrstuvwxyz012345') + expect(vm['lifetime'].to_i).to eq(4) + end + + it 'extends VM lifetime to global value if auth token is provided' do app.settings.set :config, auth: true create_ready_vm 'pool1', 'abcdefghijklmnop' @@ -325,5 +348,46 @@ describe Vmpooler::API::V1 do end end end + describe 'GET /vm/:hostname' do + it 'returns a single VM with pool lifetime' do + create_running_vm 'pool2', 'qrstuvwxyz012345' + + get "#{prefix}/vm/qrstuvwxyz012345" + expect_json(ok = true, http = 200) + + expected = { + ok: true, + qrstuvwxyz012345: { + template: 'pool2', + lifetime: 1, + running: 0.0, + state: 'running', + ip: '' + } + } + + expect(last_response.body).to eq(JSON.pretty_generate(expected)) + end + + it 'returns a single VM with global lifetime' do + create_running_vm 'pool1', 'abcdefghijklmnop' + + get "#{prefix}/vm/abcdefghijklmnop" + expect_json(ok = true, http = 200) + + expected = { + ok: true, + abcdefghijklmnop: { + template: 'pool1', + lifetime: 12, + running: 0.0, + state: 'running', + ip: '' + } + } + + expect(last_response.body).to eq(JSON.pretty_generate(expected)) + end + end end end diff --git a/vmpooler.yaml.example b/vmpooler.yaml.example index 4e54891..ba02b57 100644 --- a/vmpooler.yaml.example +++ b/vmpooler.yaml.example @@ -285,6 +285,14 @@ # - ready_ttl # How long (in minutes) to keep VMs in 'ready' queues before destroying. # (optional) +# +# - vm_lifetime +# How long (in hours) to keep VMs in 'running' queues before destroying. +# (optional; default: '24') +# +# - vm_lifetime_auth +# Same as vm_lifetime, but applied if a valid authentication token is +# included during the request. # Example: @@ -305,3 +313,5 @@ size: 5 timeout: 15 ready_ttl: 1440 + vm_lifetime: 1 + vm_lifetime_auth: 4