1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-22 18:50:08 +03:00

feature #696: Add support for accounting and monitoring

This commit is contained in:
Daniel Molina 2011-07-05 16:14:12 +02:00
parent 4edcd9ffd8
commit d323748b32
14 changed files with 1369 additions and 0 deletions

112
src/acct/accounting.rb Normal file
View File

@ -0,0 +1,112 @@
module OneWatch
require 'watch_helper'
class Accounting
def initialize(client)
@client = client
@active_vms = Array.new
end
def insert(hash)
@ptimestamp = @timestamp
@timestamp = generate_timestamp
new_active_vms = Array.new
last_active_vm = @active_vms.empty? ? -1 : @active_vms.last
if (vmpool_hash = hash['VM_POOL']) && !vmpool_hash.empty?
[vmpool_hash['VM']].flatten.each { |vm|
vm_id = vm['ID'].to_i
if vm['STATE'] == 3
new_active_vms << vm_id
end
# ACTIVE VMs (including those that are stopped in this step)
# in the last step and NEW VMs
if @active_vms.include?(vm_id) || vm['STATE'].to_i == 3
insert_vm(vm)
@active_vms.delete(vm_id)
else
# DONE/STOP VMs and non ACTIVE in the last step
next
end
}
end
# DONE VMs that were ACTIVE in the last step
@active_vms.each { |id|
vm = OpenNebula::VirtualMachine.new_with_id(id, @client)
vm.info
vm_hash = vm.to_hash
insert_vm(vm_hash)
}
# DONE VMs that did not exist in the last step
vmpool = OpenNebula::VirtualMachinePool.new(@client)
vmpool.info(-2, last_active_vm, -1, 6)
done_hash = vmpool.to_hash
if (done_vm_hash = done_hash['VM_POOL']) && !done_vm_hash.empty?
[done_vm_hash['VM']].flatten.each { |vm|
insert_vm(vm)
}
end
# Upate the active VMs
@active_vms = new_active_vms.sort
end
private
def generate_timestamp
Time.now.to_i
end
def insert_register(vm, register, history)
if register && register.seq == history['SEQ'].to_i
register.update_from_history(history)
else
reg = WatchHelper::Register.create_from_history(history)
vm.add_register(reg)
end
end
def update_history(vm, vm_sql)
last_register = vm_sql.registers.last
seq = last_register ? last_register.seq : 0
if hr = vm['HISTORY_RECORDS']
unless hr['HISTORY'].instance_of?(Array)
if hr['HISTORY']['SEQ'] == seq
# The VM has not moved from the Host
insert_register(vm_sql, last_register, hr['HISTORY'])
return
else
# Get the full HISTORY
vm = OpenNebula::VirtualMachine.new_with_id(vm['ID'], @client)
vm.info
vm_hash = vm.to_hash['VM']
hr = vm_hash['HISTORY_RECORDS']
# Insert a new entry for each new history record
[hr['HISTORY']].flatten.each { |history|
if history['SEQ'].to_i < seq
next
else
insert_register(vm_sql, last_register, history)
end
}
end
end
end
end
def insert_vm(vm)
vm_sql = WatchHelper::Vm.info(vm)
update_history(vm, vm_sql)
end
end
end

View File

@ -0,0 +1,75 @@
require 'watch_helper'
class AcctClient
def prolog_time(t1, t2, opts={})
times(t1, t2, opts) { |reg|
calculate_time(t1, t2, reg.pstime, reg.petime)
}
end
def running_time(t1, t2, opts={})
# TBD Suspened VMs
times(t1, t2, opts) { |reg|
calculate_time(t1, t2, reg.rstime, reg.retime)
}
end
def epilog_time(t1, t2, opts={})
times(t1, t2, opts) { |reg|
calculate_time(t1, t2, reg.estime, reg.eetime)
}
end
private
def times(t1, t2, opts={}, &block)
time = 0
vms = filter_vms(opts)
if vms && !vms.empty?
vms.each { |vm|
vm.registers.each { |reg|
time += block.call(reg)
}
}
end
time
end
def calculate_time(t1, t2, stime, etime)
if etime < t1 && etime != 0
return 0
elsif stime < t2 && stime != 0
if etime < t2 && etime != 0
e = etime
else
e = t2
end
s = stime > t1 ? stime : t1
return e - s
end
return 0
end
def filter_vms(opts={})
opts ||= {}
if opts[:uid]
vms = WatchHelper::Vm.filter(:uid=>opts[:uid])
elsif opts[:gid]
vms = WatchHelper::Vm.filter(:gid=>opts[:gid])
elsif opts[:hid]
vms = WatchHelper::Vm.filter(
:registers=>WatchHelper::Register.filter(:hid => opts[:hid]))
elsif opts[:vmid]
vms = WatchHelper::Vm.filter(:id=>opts[:vmid])
else
vms = WatchHelper::Vm
end
end
end

42
src/acct/monitoring.rb Normal file
View File

@ -0,0 +1,42 @@
module OneWatch
require 'watch_helper'
class Monitoring
def insert(hash)
timestamp = generate_timestamp
if (pool_hash = hash["#{resource}_POOL"]) && !pool_hash.empty?
[pool_hash["#{resource}"]].flatten.each { |elem|
sql = sql_elem(elem)
sql.add_share(elem, timestamp)
}
end
end
private
def generate_timestamp
Time.now.to_i
end
end
class VmMonitoring < Monitoring
def resource
'VM'
end
def sql_elem(elem)
WatchHelper::Vm.info(elem)
end
end
class HostMonitoring < Monitoring
def resource
'HOST'
end
def sql_elem(elem)
WatchHelper::Host.info(elem)
end
end
end

333
src/acct/test/1Vm1His.rb Normal file
View File

@ -0,0 +1,333 @@
require 'helper/test_helper.rb'
describe "1 Vm 1 History" do
before(:each) do
clean_db
@mock_client = MockClient.new
@accounting = OneWatch::Accounting.new(@mock_client)
@watch_client = AcctClient.new
@db = WatchHelper::DB
check_lines(0,0)
end
it "Prolog testing" do
ts1 = 100
@accounting.set_mock_timestamp(ts1)
@accounting.insert(create_vmpool_hash)
check_lines(0,0)
ts2 = 200
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:pstime => 150,
:petime => 0,
:rstime => 0,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = ts2 - history[:pstime]
warn "* T1 PSTIME T2"
@watch_client.prolog_time(ts1, ts2).to_i.should eql(sum)
warn " - By User"
@watch_client.prolog_time(ts1, ts2, :uid => 2).to_i.should eql(sum)
warn " - By Host"
@watch_client.prolog_time(ts1, ts2, :hid => 7).to_i.should eql(sum)
warn " - By Vm"
@watch_client.prolog_time(ts1, ts2, :vmid => 1).to_i.should eql(sum)
warn " - Non existent User"
@watch_client.prolog_time(ts1, ts2, :uid => 555).to_i.should eql(0)
warn " - Non existent Host"
@watch_client.prolog_time(ts1, ts2, :hid => 555).to_i.should eql(0)
warn " - Non existent Vm"
@watch_client.prolog_time(ts1, ts2, :vmid => 555).to_i.should eql(0)
warn "* PSTIME T1 T2"
@watch_client.prolog_time(160, ts2).to_i.should eql(sum-10)
warn "* T1 PSTIME T2-10"
@watch_client.prolog_time(ts1, ts2-10).to_i.should eql(sum-10)
warn "* T1 T2 PSTIME"
@watch_client.prolog_time(110, 130).to_i.should eql(0)
warn "* Non Epilog time"
@watch_client.epilog_time(ts1, ts2).to_i.should eql(0)
warn "* Non Running time"
@watch_client.running_time(ts1, ts2).to_i.should eql(0)
ts3 = 300
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:pstime => 150,
:petime => 240,
:rstime => 0,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = history[:petime] - history[:pstime]
warn "* T1 PSTIME PETIME T3"
@watch_client.prolog_time(ts1, ts3).to_i.should eql(sum)
warn " - By User"
@watch_client.prolog_time(ts1, ts3, :uid => 2).to_i.should eql(sum)
warn " - By Host"
@watch_client.prolog_time(ts1, ts3, :hid => 7).to_i.should eql(sum)
warn " - By Vm"
@watch_client.prolog_time(ts1, ts3, :vmid => 1).to_i.should eql(sum)
warn "* T1 PSTIME T3 PETIME"
@watch_client.prolog_time(ts1, 230).to_i.should eql(230 - history[:pstime])
warn "* PSTIME T1 PETIME T3"
@watch_client.prolog_time(160, ts3).to_i.should eql(history[:petime] - 160)
warn "* PSTIME T1 T3 PETIME"
@watch_client.prolog_time(160, 230).to_i.should eql(230 - 160)
end
it "Running testing" do
ts1 = 100
@accounting.set_mock_timestamp(ts1)
@accounting.insert(create_vmpool_hash)
check_lines(0,0)
ts2 = 200
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:pstime => 150,
:petime => 155,
:rstime => 155,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = ts2 - history[:rstime]
warn "* T1 RSTIME T2"
@watch_client.running_time(ts1, ts2).to_i.should eql(sum)
warn " - By User"
@watch_client.running_time(ts1, ts2, :uid => 2).to_i.should eql(sum)
warn " - By Host"
@watch_client.running_time(ts1, ts2, :hid => 7).to_i.should eql(sum)
warn " - By Vm"
@watch_client.running_time(ts1, ts2, :vmid => 1).to_i.should eql(sum)
warn " - Non existent User"
@watch_client.running_time(ts1, ts2, :uid => 555).to_i.should eql(0)
warn " - Non existent Host"
@watch_client.running_time(ts1, ts2, :hid => 555).to_i.should eql(0)
warn " - Non existent Vm"
@watch_client.running_time(ts1, ts2, :vmid => 555).to_i.should eql(0)
warn "* RSTIME T1 T2"
@watch_client.running_time(160, ts2).to_i.should eql(ts2-160)
warn "* T1 RSTIME T2-10"
@watch_client.running_time(ts1, ts2-10).to_i.should eql(sum-10)
warn "* T1 T2 RSTIME"
@watch_client.running_time(110, 130).to_i.should eql(0)
warn "* Non Epilog time"
@watch_client.epilog_time(ts1, ts2).to_i.should eql(0)
warn "* Non Prolog time"
@watch_client.prolog_time(ts1, ts2).to_i.should eql(5)
ts3 = 300
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:pstime => 150,
:petime => 155,
:rstime => 155,
:retime => 230,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = history[:retime] - history[:rstime]
warn "* T1 PSTIME PETIME T3"
@watch_client.running_time(ts1, ts3).to_i.should eql(sum)
warn " - By User"
@watch_client.running_time(ts1, ts3, :uid => 2).to_i.should eql(sum)
warn " - By Host"
@watch_client.running_time(ts1, ts3, :hid => 7).to_i.should eql(sum)
warn " - By Vm"
@watch_client.running_time(ts1, ts3, :vmid => 1).to_i.should eql(sum)
warn "* T1 PSTIME T3 PETIME"
@watch_client.running_time(ts1, 230).to_i.should eql(230 - history[:rstime])
warn "* PSTIME T1 PETIME T3"
@watch_client.running_time(160, ts3).to_i.should eql(history[:retime] - 160)
warn "* PSTIME T1 T3 PETIME"
@watch_client.running_time(160, 230).to_i.should eql(230 - 160)
end
it "Epilog testing" do
ts1 = 100
@accounting.set_mock_timestamp(ts1)
@accounting.insert(create_vmpool_hash)
check_lines(0,0)
ts2 = 200
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:pstime => 150,
:petime => 155,
:rstime => 155,
:retime => 170,
:estime => 180,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = ts2 - history[:estime]
warn "* T1 ESTIME T2"
@watch_client.epilog_time(ts1, ts2).to_i.should eql(sum)
warn " - By User"
@watch_client.epilog_time(ts1, ts2, :uid => 2).to_i.should eql(sum)
warn " - By Host"
@watch_client.epilog_time(ts1, ts2, :hid => 7).to_i.should eql(sum)
warn " - By Vm"
@watch_client.epilog_time(ts1, ts2, :vmid => 1).to_i.should eql(sum)
warn " - Non existent User"
@watch_client.epilog_time(ts1, ts2, :uid => 555).to_i.should eql(0)
warn " - Non existent Host"
@watch_client.epilog_time(ts1, ts2, :hid => 555).to_i.should eql(0)
warn " - Non existent Vm"
@watch_client.epilog_time(ts1, ts2, :vmid => 555).to_i.should eql(0)
warn "* ESTIME T1 T2"
@watch_client.epilog_time(190, ts2).to_i.should eql(ts2-190)
warn "* T1 ESTIME T2-10"
@watch_client.epilog_time(ts1, ts2-10).to_i.should eql(sum-10)
warn "* T1 T2 ESTIME"
@watch_client.epilog_time(110, 130).to_i.should eql(0)
warn "* Non Running time"
@watch_client.running_time(ts1, ts2).to_i.should eql(15)
warn "* Non Prolog time"
@watch_client.prolog_time(ts1, ts2).to_i.should eql(5)
ts3 = 300
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:pstime => 150,
:petime => 155,
:rstime => 155,
:retime => 170,
:estime => 180,
:eetime => 230,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = history[:eetime] - history[:estime]
warn "* T1 PSTIME PETIME T3"
@watch_client.epilog_time(ts1, ts3).to_i.should eql(sum)
warn " - By User"
@watch_client.epilog_time(ts1, ts3, :uid => 2).to_i.should eql(sum)
warn " - By Host"
@watch_client.epilog_time(ts1, ts3, :hid => 7).to_i.should eql(sum)
warn " - By Vm"
@watch_client.epilog_time(ts1, ts3, :vmid => 1).to_i.should eql(sum)
warn "* T1 PSTIME T3 PETIME"
@watch_client.epilog_time(ts1, 230).to_i.should eql(230 - history[:estime])
warn "* PSTIME T1 PETIME T3"
@watch_client.epilog_time(190, ts3).to_i.should eql(history[:eetime] - 190)
warn "* PSTIME T1 T3 PETIME"
@watch_client.epilog_time(190, 220).to_i.should eql(220 - 190)
end
end

99
src/acct/test/1VmXHis.rb Normal file
View File

@ -0,0 +1,99 @@
require 'helper/test_helper.rb'
describe "1 Vm X History" do
before(:each) do
clean_db
@mock_client = MockClient.new
@accounting = OneWatch::Accounting.new(@mock_client)
@watch_client = AcctClient.new
@db = WatchHelper::DB
check_lines(0,0)
end
it "Running testing" do
ts1 = 100
@accounting.set_mock_timestamp(ts1)
@accounting.insert(create_vmpool_hash)
check_lines(0,0)
ts2 = 200
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:seq => 0,
:pstime => 150,
:petime => 155,
:rstime => 155,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = ts2 - history[:rstime]
warn "* T1 RSTIME T2"
@watch_client.running_time(ts1, ts2).to_i.should eql(sum)
ts3 = 300
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
{
:hid => 7,
:seq => 0,
:pstime => 150,
:petime => 155,
:rstime => 155,
:retime => 230,
:estime => 230,
:eetime => 260,
:reason => 2
},
{
:hid => 8,
:seq => 1,
:pstime => 270,
:petime => 275,
:rstime => 275,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
}
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,2)
h1 = values[:history].first
sum1 = h1[:retime] - h1[:rstime]
h2 = values[:history].last
sum2 = ts3 - h2[:rstime]
warn "* T1 RSTIME1 RETIME1 RSTIME1 T2"
@watch_client.running_time(ts1, ts3).to_i.should eql(sum1 + sum2)
end
end

91
src/acct/test/XVm1His.rb Normal file
View File

@ -0,0 +1,91 @@
require 'helper/test_helper.rb'
describe "X Vm 1 History" do
before(:each) do
clean_db
@mock_client = MockClient.new
@accounting = OneWatch::Accounting.new(@mock_client)
@watch_client = AcctClient.new
@db = WatchHelper::DB
check_lines(0,0)
end
it "Running testing" do
ts1 = 100
@accounting.set_mock_timestamp(ts1)
@accounting.insert(create_vmpool_hash)
check_lines(0,0)
ts2 = 200
@accounting.set_mock_timestamp(ts2)
values = {
:uid => 2,
:gid => 4,
:history => [
:hid => 6,
:seq => 0,
:pstime => 150,
:petime => 155,
:rstime => 155,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@accounting.insert(create_vmpool_hash)
check_lines(1,1)
history = values[:history].first
sum = ts2 - history[:rstime]
warn "* T1 RSTIME T2"
@watch_client.running_time(ts1, ts2).to_i.should eql(sum)
ts3 = 300
@accounting.set_mock_timestamp(ts3)
values2 = {
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:seq => 0,
:pstime => 220,
:petime => 260,
:rstime => 260,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(2, values2)
@accounting.insert(create_vmpool_hash)
check_lines(2,2)
history1 = values[:history].first
sum1 = ts3 - history1[:rstime]
history2 = values2[:history].first
sum2 = ts3 - history2[:rstime]
warn "* T1 RSTIME T2"
@watch_client.running_time(ts1, ts3).to_i.should eql(sum1 + sum2)
@watch_client.running_time(ts1, ts3, :vmid=>1).to_i.should eql(sum1)
@watch_client.running_time(ts1, ts3, :vmid=>2).to_i.should eql(sum2)
@watch_client.running_time(ts1, ts3, :uid=>2).to_i.should eql(sum1 + sum2)
@watch_client.running_time(ts1, ts3, :hid=>6).to_i.should eql(sum1)
@watch_client.running_time(ts1, ts3, :hid=>7).to_i.should eql(sum2)
end
end

1
src/acct/test/fixtures/empty_pool.xml vendored Normal file
View File

@ -0,0 +1 @@
<VM_POOL/>

46
src/acct/test/fixtures/vm.xml vendored Normal file
View File

@ -0,0 +1,46 @@
<VM>
<ID><%= id %></ID>
<UID><%= vm[:uid] ? vm[:uid] : 0 %></UID>
<GID><%= vm[:gid] ? vm[:gid] : 0 %></GID>
<NAME><%= vm[:name] ? vm[:uid] : 'pepe' %></NAME>
<LAST_POLL><%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %></LAST_POLL>
<STATE><%= vm[:state] ? vm[:state] : 3 %></STATE>
<LCM_STATE>3</LCM_STATE>
<STIME>1309275252</STIME>
<ETIME>0</ETIME>
<DEPLOY_ID>dummy</DEPLOY_ID>
<MEMORY><%= vm[:memory] ? vm[:memory] : 128 %></MEMORY>
<CPU><%= vm[:cpu] ? vm[:cpu] : 1 %></CPU>
<NET_TX><%= vm[:net_tx] ? vm[:net_tx] : 0 %></NET_TX>
<NET_RX><%= vm[:net_rx] ? vm[:net_rx] : 0 %></NET_RX>
<TEMPLATE>
<CPU><![CDATA[1]]></CPU>
<MEMORY><![CDATA[1024]]></MEMORY>
<NAME><![CDATA[PEPEPE]]></NAME>
<VCPU><![CDATA[1]]></VCPU>
<VMID><![CDATA[4]]></VMID>
</TEMPLATE>
<% if history = vm[:history] %>
<HISTORY_RECORDS>
<% history.each do |h| %>
<HISTORY>
<SEQ><%= h[:seq] ? h[:seq] : 0 %></SEQ>
<HOSTNAME><%= h[:hostname] ? h[:hostname] : "kvxen" %></HOSTNAME>
<VM_DIR>/Users/dmolina/trabajo/acctmoni/install/var/</VM_DIR>
<HID><%= h[:hid] ? h[:hid] : 0 %></HID>
<STIME>1309275256</STIME>
<ETIME>0</ETIME>
<VMMMAD>vmm_dummy</VMMMAD>
<TMMAD>tm_dummy</TMMAD>
<PSTIME><%= h[:pstime] ? h[:pstime] : 0 %></PSTIME>
<PETIME><%= h[:petime] ? h[:petime] : 0 %></PETIME>
<RSTIME><%= h[:rstime] ? h[:rstime] : 0 %></RSTIME>
<RETIME><%= h[:retime] ? h[:retime] : 0 %></RETIME>
<ESTIME><%= h[:estime] ? h[:estime] : 0 %></ESTIME>
<EETIME><%= h[:eetime] ? h[:eetime] : 0 %></EETIME>
<REASON><%= h[:reason] ? h[:reason] : 0 %></REASON>
</HISTORY>
<% end %>
</HISTORY_RECORDS>
<% end %>
</VM>

49
src/acct/test/fixtures/vmpool.xml vendored Normal file
View File

@ -0,0 +1,49 @@
<VM_POOL>
<% vms.each do |id,vm| %>
<VM>
<ID><%= id %></ID>
<UID><%= vm[:uid] ? vm[:uid] : 0 %></UID>
<GID><%= vm[:gid] ? vm[:gid] : 0 %></GID>
<NAME><%= vm[:name] ? vm[:uid] : 'pepe' %></NAME>
<LAST_POLL><%= vm[:last_poll] ? vm[:last_poll] : '1309275256' %></LAST_POLL>
<STATE><%= vm[:state] ? vm[:state] : 3 %></STATE>
<LCM_STATE>3</LCM_STATE>
<STIME>1309275252</STIME>
<ETIME>0</ETIME>
<DEPLOY_ID>dummy</DEPLOY_ID>
<MEMORY><%= vm[:memory] ? vm[:memory] : 128 %></MEMORY>
<CPU><%= vm[:cpu] ? vm[:cpu] : 1 %></CPU>
<NET_TX><%= vm[:net_tx] ? vm[:net_tx] : 0 %></NET_TX>
<NET_RX><%= vm[:net_rx] ? vm[:net_rx] : 0 %></NET_RX>
<TEMPLATE>
<CPU><![CDATA[1]]></CPU>
<MEMORY><![CDATA[1024]]></MEMORY>
<NAME><![CDATA[PEPEPE]]></NAME>
<VCPU><![CDATA[1]]></VCPU>
<VMID><![CDATA[4]]></VMID>
</TEMPLATE>
<% if history = vm[:history] %>
<HISTORY_RECORDS>
<% h = history.last %>
<HISTORY>
<SEQ><%= h[:seq] ? h[:seq] : 0 %></SEQ>
<HOSTNAME><%= h[:hostname] ? h[:hostname] : "kvxen" %></HOSTNAME>
<VM_DIR>/Users/dmolina/trabajo/acctmoni/install/var/</VM_DIR>
<HID><%= h[:hid] ? h[:hid] : 0 %></HID>
<STIME>1309275256</STIME>
<ETIME>0</ETIME>
<VMMMAD>vmm_dummy</VMMMAD>
<TMMAD>tm_dummy</TMMAD>
<PSTIME><%= h[:pstime] ? h[:pstime] : 0 %></PSTIME>
<PETIME><%= h[:petime] ? h[:petime] : 0 %></PETIME>
<RSTIME><%= h[:rstime] ? h[:rstime] : 0 %></RSTIME>
<RETIME><%= h[:retime] ? h[:retime] : 0 %></RETIME>
<ESTIME><%= h[:estime] ? h[:estime] : 0 %></ESTIME>
<EETIME><%= h[:eetime] ? h[:eetime] : 0 %></EETIME>
<REASON><%= h[:reason] ? h[:reason] : 0 %></REASON>
</HISTORY>
</HISTORY_RECORDS>
<% end %>
</VM>
<% end %>
</VM_POOL>

View File

@ -0,0 +1,49 @@
require 'erb'
FPATH = "./fixtures/"
class MockClient
def initialize
@vmpool = File.read("./fixtures/empty_pool.xml")
@done_vmpool = File.read("./fixtures/empty_pool.xml")
@vms = Hash.new
@done_vms = Hash.new
end
def call(action, *args)
xmlrpc_action = "one."+action
case xmlrpc_action
when "one.vm.info"
id = args[0]
vm = @vms[id]
return ERB.new(File.read(FPATH+'vm.xml')).result(binding)
when "one.vmpool.info"
case args[3]
when -1
return File.read("./fixtures/empty_pool.xml") if @vms.empty?
vms = @vms
return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding)
when 6 then
return File.read("./fixtures/empty_pool.xml") if @done_vms.empty?
vms = @done_vms
return ERB.new(File.read(FPATH+'vmpool.xml')).result(binding)
end
end
end
def add_vm(id, values)
if values[:state] == 6
@done_vms[id] = values
elsif
@vms[id] = values
end
end
def delete_vm(id)
@vms.delete(id)
@vms_done.delete(id)
end
end

View File

@ -0,0 +1,71 @@
require 'rubygems'
require 'sequel'
ONE_LOCATION = ENV['ONE_LOCATION']
if !ONE_LOCATION
RUBY_LIB_LOCATION="/usr/lib/one/ruby"
else
RUBY_LIB_LOCATION=ONE_LOCATION+"/lib/ruby"
end
$: << RUBY_LIB_LOCATION
require 'OpenNebula'
$: << './helper'
$: << '.'
$: << '..'
require 'examples/acct_client'
require 'watch_client'
require 'mock_client'
require 'accounting'
require 'monitoring'
module OneWatch
class Accounting
def set_mock_timestamp(t)
@mock_timestamp = t
end
def generate_timestamp
@mock_timestamp
end
end
class Monitoring
def set_mock_timestamp(t)
@mock_timestamp = t
end
def generate_timestamp
@mock_timestamp
end
end
end
def create_vmpool_hash
@vm_pool = OpenNebula::VirtualMachinePool.new(@mock_client, -2)
@vm_pool.info
hash = @vm_pool.to_hash
end
def clean_db
begin
WatchHelper::Register.destroy
WatchHelper::Metric.destroy
WatchHelper::VmShare.destroy
WatchHelper::HostShare.destroy
WatchHelper::Vm.destroy
WatchHelper::Host.destroy
rescue Exception => e
warn e.message
end
end
def check_lines(*args)
@db[:vms].count.should eql(args[0])
@db[:registers].count.should eql(args[1])
end

View File

@ -0,0 +1,56 @@
require 'helper/test_helper.rb'
describe "1 Vm 1 10 steps" do
before(:each) do
clean_db
@mock_client = MockClient.new
@monitoring = OneWatch::VmMonitoring.new
@watch_client = OneWatchClient::WatchClient.new
@db = WatchHelper::DB
@db[:vms].count.should eql(0)
end
it "CPU testing" do
ts1 = 100
@monitoring.set_mock_timestamp(ts1)
@monitoring.insert(create_vmpool_hash)
@db[:vms].count.should eql(0)
10.times { |i|
ts2 = 200+100*i
@monitoring.set_mock_timestamp(ts2)
values = {
:cpu => 80+i,
:memory => 122+i,
:net_tx => 200+i,
:net_rx => 134+i,
:last_poll => 1309275256+i,
:uid => 2,
:gid => 4,
:history => [
:hid => 7,
:pstime => 150,
:petime => 0,
:rstime => 0,
:retime => 0,
:estime => 0,
:eetime => 0,
:reason => 0
]
}
@mock_client.add_vm(1, values)
@monitoring.insert(create_vmpool_hash)
@db[:vms].count.should eql(1)
@db[:vm_shares].count.should eql(1+i > 5 ? 5 : 1+i)
pp @watch_client.vm_monitoring(1)
}
end
end

30
src/acct/watch_client.rb Normal file
View File

@ -0,0 +1,30 @@
module OneWatchClient
require 'watch_helper'
require 'json'
class WatchClient
def vm_monitoring(id, opts=[])
hash = Hash.new
hash[:resource] = "VM"
hash[:id] = id
mon = Hash.new
opts.each { |opt|
next unless WatchHelper::VM_SHARE.has_key?(opt.to_sym)
mon[opt] = Array.new
}
# TBD Check if VM exists
WatchHelper::Vm[id].vm_shares_dataset.map { |vm|
opts.each { |opt|
next unless WatchHelper::VM_SHARE.has_key?(opt.to_sym)
mon[opt] << [vm.last_poll, vm.send(opt.to_sym)]
}
}
hash[:monitoring] = mon
puts JSON.pretty_generate hash
end
end
end

315
src/acct/watch_helper.rb Normal file
View File

@ -0,0 +1,315 @@
module WatchHelper
DB = Sequel.connect('sqlite:///tmp/test_one_acct.db')
class Register < Sequel::Model
plugin :schema
set_schema do
foreign_key :vm_id, :vms
Integer :hid
String :hostname
Integer :seq
Integer :pstime
Integer :petime
Integer :rstime
Integer :retime
Integer :estime
Integer :eetime
Integer :reason
primary_key [:vm_id, :seq]
end
create_table unless table_exists?
unrestrict_primary_key
many_to_one :vm
def update_from_history(history)
self.seq = history['SEQ']
self.hostname = history['HOSTNAME']
self.hid = history['HID']
self.pstime = history['PSTIME']
self.petime = history['PETIME']
self.rstime = history['RSTIME']
self.retime = history['RETIME']
self.estime = history['ESTIME']
self.eetime = history['EETIME']
self.reason = history['REASON']
self.save
end
def self.create_from_history(history)
a = Register.create(
:seq => history['SEQ'],
:hostname => history['HOSTNAME'],
:hid => history['HID'],
:pstime => history['PSTIME'],
:petime => history['PETIME'],
:rstime => history['RSTIME'],
:retime => history['RETIME'],
:estime => history['ESTIME'],
:eetime => history['EETIME'],
:reason => history['REASON']
)
end
end
class Metric < Sequel::Model
plugin :schema
set_schema do
foreign_key :vm_id, :vms
Integer :timestamp
Integer :ptimestamp
Integer :net_rx
Integer :net_tx
primary_key [:vm_id, :timestamp]
end
create_table unless table_exists?
unrestrict_primary_key
many_to_one :vm
end
class Vm < Sequel::Model
plugin :schema
set_schema do
Integer :id, :primary_key=>true
String :name
Integer :uid
Integer :gid
Integer :mem
Integer :cpu
Integer :vcpu
Integer :stime
Integer :etime
end
create_table unless table_exists?
unrestrict_primary_key
# Accounting
one_to_many :registers, :order=>:seq
one_to_many :metrics
# Monitoring
one_to_many :vm_shares, :before_add=>:control_regs, :order=>:timestamp
def self.info(vm)
Vm.find_or_create(:id=>vm['ID']) { |v|
v.uid = vm['UID'].to_i
v.name = vm['NAME']
v.gid = vm['GID'].to_i
v.mem = vm['MEMORY'].to_i
v.cpu = vm['CPU'].to_i
v.vcpu = vm['VCPU'].to_i
v.stime = vm['STIME'].to_i
v.etime = vm['ETIME'].to_i
}
end
def add_share(vm, timestamp)
vs = VmShare.create_from_vm(vm, timestamp)
self.add_vm_share(vs)
end
private
def control_regs(share)
if self.vm_shares.count > 4
self.vm_shares.first.delete
end
end
end
class Host < Sequel::Model
plugin :schema
set_schema do
Integer :id, :primary_key=>true
String :name
Integer :im_mad
Integer :vm_mad
Integer :tm_mad
end
create_table unless table_exists?
unrestrict_primary_key
# Monitoring
one_to_many :host_shares, :before_add=>:control_regs, :order=>:timestamp
def add_share(host, timestamp)
hs = HostShare.create_from_host(host, timestamp)
self.add_host_share(hs)
end
private
def control_regs(share)
if self.host_shares.count > 4
self.host_shares.first.delete
end
end
end
HOST_SHARE = {
:disk_usage => {
:type => Integer,
:path => 'DISK_USAGE'
},
:mem_usage => {
:type => Integer,
:path => 'MEM_USAGE'
},
:cpu_usage => {
:type => Integer,
:path => 'CPU_USAGE'
},
:max_disk => {
:type => Integer,
:path => 'MAX_DISK'
},
:max_mem => {
:type => Integer,
:path => 'MAX_MEM'
},
:mem_cpu => {
:type => Integer,
:path => 'MAX_CPU'
},
:free_disk => {
:type => Integer,
:path => 'FREE_DISK'
},
:free_mem => {
:type => Integer,
:path => 'FREE_MEM'
},
:free_cpu => {
:type => Integer,
:path => 'FREE_CPU'
},
:used_disk => {
:type => Integer,
:path => 'USED_DISK'
},
:used_mem => {
:type => Integer,
:path => 'USED_MEM'
},
:used_cpu => {
:type => Integer,
:path => 'USED_CPU'
},
:rvms => {
:type => Integer,
:path => 'RUNNING_VMS'
}
}
class HostShare < Sequel::Model
plugin :schema
set_schema do
foreign_key :host_id, :hosts
Integer :last_poll
Integer :timestamp
HOST_SHARE.each { |key,value|
column key, value[:type]
}
primary_key [:host_id, :timestamp]
end
create_table unless table_exists?
unrestrict_primary_key
many_to_one :host
def self.create_from_host(host, timestamp)
hash = {
:timestamp => timestamp,
:last_poll => host['LAST_MON_TIME'],
:state => host['STATE'],
}
host_share = host['HOST_SHARE']
HOST_SHARE.each { |key,value|
hash[key] = host_share[value[:path]]
}
HostShare.create(hash)
end
end
VM_SHARE = {
:cpu => {
:type => Integer,
:path => 'CPU'
},
:memory => {
:type => Integer,
:path => 'MEMORY'
},
:net_tx => {
:type => Integer,
:path => 'NET_TX'
},
:net_rx => {
:type => Integer,
:path => 'NET_RX'
}
}
class VmShare < Sequel::Model
plugin :schema
set_schema do
foreign_key :vm_id, :vms
Integer :state
Integer :lcm_state
Integer :last_poll
Integer :timestamp
VM_SHARE.each { |key,value|
column key, value[:type]
}
primary_key [:vm_id, :timestamp]
end
create_table unless table_exists?
unrestrict_primary_key
many_to_one :vm
def self.create_from_vm(vm, timestamp)
hash = {
:timestamp => timestamp,
:last_poll => vm['LAST_POLL'],
:state => vm['STATE'],
:lcm_state => vm['LCM_STATE'],
}
VM_SHARE.each { |key,value|
hash[key] = vm[value[:path]]
}
VmShare.create(hash)
end
end
end