From 74082bdd4ac245e786dcb2efcda3f525866a1ec1 Mon Sep 17 00:00:00 2001 From: Alejandro Huertas Date: Mon, 27 May 2019 14:52:03 +0200 Subject: [PATCH] B #3269: onedb purge-done eat too much RAM * Process done VMs in pages, instead of all together * Add new method to iterate over pages * Add new CLI paramter to specify pages size --- src/oca/ruby/opennebula/pool.rb | 36 ++++++++++++++++++++++++++++----- src/onedb/onedb | 10 ++++++++- src/onedb/onedb_live.rb | 30 +++++++++++---------------- 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/oca/ruby/opennebula/pool.rb b/src/oca/ruby/opennebula/pool.rb index 53bc10f5d2e..92d1490409c 100644 --- a/src/oca/ruby/opennebula/pool.rb +++ b/src/oca/ruby/opennebula/pool.rb @@ -233,10 +233,12 @@ def info_paginated(size) # Gets a hash from a info page from pool # size:: nil => default page size - # > 0 => page size + # > 0 => page size # current first element of the page + # extended true to get extended information + # state state of the objects # hash:: return page as a hash - def get_page(size, current, extended = false) + def get_page(size, current, extended = false, state = -1) rc = nil if PAGINATED_POOLS.include?(@pool_name) @@ -249,19 +251,43 @@ def get_page(size, current, extended = false) end size = OpenNebula.pool_page_size if (!size || size == 0) - rc = @client.call(method, @user_id, current, -size, -1) + rc = @client.call(method, @user_id, current, -size, state) initialize_xml(rc, @pool_name) else rc = info end - return rc + return rc + end + + # Iterates over pool pages + # size:: nil => default page size + # > 0 => page size + # state state of objects + # delete true to take always the first page + def each_page(size, state = -1, extended = false, delete = false) + current = 0 + element = @pool_name.split('_')[0] + page = OpenNebula::XMLElement.new + + loop do + page.initialize_xml(get_page(size, current, extended, state), + @pool_name) + + break if page["//#{element}"].nil? + + page.each("//#{element}") do |obj| + yield(obj) + end + + current += size unless delete + end end # Return true if pool is paginated def is_paginated? - PAGINATED_POOLS.include?(@pool_name) + PAGINATED_POOLS.include?(@pool_name) end end end diff --git a/src/onedb/onedb b/src/onedb/onedb index 9d9f0efa542..a0464d665bd 100755 --- a/src/onedb/onedb +++ b/src/onedb/onedb @@ -291,6 +291,14 @@ DELETE= { :description => "Delete all matched xpaths" } +PAGES = { + :name => 'pages', + :short => '-p pages', + :large => '--pages pages', + :description => 'Nummber of pages to purge VMs', + :format => Integer +} + cmd=CommandParser::CmdParser.new(ARGV) do description <<-EOT.unindent This command enables the user to manage the OpenNebula database. It @@ -500,7 +508,7 @@ cmd=CommandParser::CmdParser.new(ARGV) do EOT command :'purge-done', purge_done_desc, - :options => [START_TIME, END_TIME] do + :options => [START_TIME, END_TIME, PAGES] do begin action = OneDBLive.new action.purge_done_vm(options) diff --git a/src/onedb/onedb_live.rb b/src/onedb/onedb_live.rb index c04977371cd..26a74b70b3a 100644 --- a/src/onedb/onedb_live.rb +++ b/src/onedb/onedb_live.rb @@ -4,7 +4,8 @@ class OneDBLive - EDITOR_PATH='/bin/vi' + EDITOR_PATH = '/bin/vi' + PAGES = 100 def initialize @client = nil @@ -206,30 +207,23 @@ def purge_history(options = {}) end def purge_done_vm(options = {}) - vmpool = OpenNebula::VirtualMachinePool.new(client) - vmpool.info(OpenNebula::Pool::INFO_ALL, - -1, - -1, - OpenNebula::VirtualMachine::VM_STATE.index('DONE')) - - ops = { - start_time: 0, - end_time: Time.now - }.merge(options) - + ops = { :start_time => 0, + :end_time => Time.now, + :pages => PAGES }.merge(options) + vmpool = OpenNebula::VirtualMachinePool.new(client) start_time = ops[:start_time].to_i end_time = ops[:end_time].to_i + done = OpenNebula::VirtualMachine::VM_STATE.index('DONE') - last_id = vmpool["/VM_POOL/VM[last()]/ID"] + vmpool.each_page(ops[:pages], done, false, true) do |obj| + print "VM with ID: #{obj['ID']} purged \r" - vmpool.each do |vm| - print percentage_line(vm.id, last_id, true) + time = obj['ETIME'].to_i - time = vm["ETIME"].to_i next unless time >= start_time && time < end_time - delete("vm_pool", "oid = #{vm.id}", false) - delete("history", "vid = #{vm.id}", false) + delete('vm_pool', "oid = #{obj['ID']}", false) + delete('history', "vid = #{obj['ID']}", false) end end