1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-01 05:47:01 +03:00

F #2183: Use pager for list commands (e.g. onevm list). Support for

custom ordering (by ID) in list API calls, this can be set per user,
group and default in oned.conf

(cherry picked from commit 21fe3116818cfceda4cb84b02662b3f475eb8ce9)
This commit is contained in:
Ruben S. Montero 2018-07-24 11:41:41 +02:00
parent ccdbb99e9d
commit cdd5222e86
28 changed files with 418 additions and 132 deletions

View File

@ -186,13 +186,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "CLUSTER_POOL", Cluster::table, where,
limit);
limit, desc);
};
/**

View File

@ -131,13 +131,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "DATASTORE_POOL", Datastore::table, where,
limit);
limit, desc);
};
/**

View File

@ -82,13 +82,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "DOCUMENT_POOL", Document::table, where,
limit);
limit, desc);
};
/**

View File

@ -148,10 +148,12 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit);
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc);
private:

View File

@ -221,12 +221,14 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "HOST_POOL", Host::table, where, limit);
return PoolSQL::dump(oss, "HOST_POOL", Host::table, where, limit, desc);
};
/**

View File

@ -134,12 +134,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "IMAGE_POOL", Image::table, where, limit);
return PoolSQL::dump(oss, "IMAGE_POOL", Image::table, where, limit,
desc);
}
/**

View File

@ -122,14 +122,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(std::ostringstream& oss, const std::string& where,
const std::string& limit)
const std::string& limit, bool desc)
{
return PoolSQL::dump(oss, "MARKETPLACEAPP_POOL", MarketPlaceApp::table,
where, limit);
where, limit, desc);
};
/** Update a particular MarketPlaceApp

View File

@ -102,14 +102,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(std::ostringstream& oss, const std::string& where,
const std::string& limit)
const std::string& limit, bool desc)
{
return PoolSQL::dump(oss, "MARKETPLACE_POOL", MarketPlace::table, where,
limit);
limit, desc);
};
/**

View File

@ -168,12 +168,13 @@ public:
* query
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where)
int dump(ostringstream& oss, const string& where, bool desc)
{
return dump(oss, where, "");
return dump(oss, where, "", desc);
}
/**
@ -182,12 +183,13 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
virtual int dump(ostringstream& oss, const string& where,
const string& limit) = 0;
const string& limit, bool desc) = 0;
// -------------------------------------------------------------------------
// Function to generate dump filters
@ -276,6 +278,7 @@ protected:
* @param table Pool table name
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
@ -283,7 +286,8 @@ protected:
const string& elem_name,
const char * table,
const string& where,
const string& limit);
const string& limit,
bool desc);
/**
* Dumps the pool in XML format. A filter can be also added to the
@ -292,15 +296,17 @@ protected:
* @param elem_name Name of the root xml pool name
* @param table Pool table name
* @param where filter for the objects, defaults to all
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss,
const string& elem_name,
const char * table,
const string& where)
const string& where,
bool desc)
{
return dump(oss, elem_name, table, where, "");
return dump(oss, elem_name, table, where, "", desc);
}
/**

View File

@ -96,13 +96,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "SECURITY_GROUP_POOL", SecurityGroup::table,
where, limit);
where, limit, desc);
};
/**

View File

@ -178,10 +178,12 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit);
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc);
/**
* Name for the OpenNebula core authentication process

View File

@ -100,13 +100,15 @@ public:
* @param os the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(std::ostringstream& os, const std::string& where,
const std::string& limit)
const std::string& limit, bool desc)
{
return PoolSQL::dump(os, "VM_GROUP_POOL", VMGroup::table, where, limit);
return PoolSQL::dump(os, "VM_GROUP_POOL", VMGroup::table, where, limit,
desc);
};
/**

View File

@ -73,13 +73,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "VMTEMPLATE_POOL", VMTemplate::table, where,
limit);
limit, desc);
};
/**

View File

@ -91,12 +91,14 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "VDC_POOL", Vdc::table, where, limit);
return PoolSQL::dump(oss, "VDC_POOL", Vdc::table, where, limit, desc);
};
/**

View File

@ -246,13 +246,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "VM_POOL", VirtualMachine::table, where,
limit);
limit, desc);
};
/**

View File

@ -133,13 +133,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "VNET_POOL", VirtualNetwork::table, where,
limit);
limit, desc);
}
/**

View File

@ -84,13 +84,15 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "VROUTER_POOL", VirtualRouter::table, where,
limit);
limit, desc);
};
/**

View File

@ -92,12 +92,14 @@ public:
* @param oss the output stream to dump the pool contents
* @param where filter for the objects, defaults to all
* @param limit parameters used for pagination
* @param desc descending order of pool elements
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& where, const string& limit)
int dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
return PoolSQL::dump(oss, "ZONE_POOL", Zone::table, where, limit);
return PoolSQL::dump(oss, "ZONE_POOL", Zone::table, where, limit, desc);
};
/**

View File

@ -103,6 +103,16 @@ VNC_PORTS = [
# RESERVED = "6800, 6801, 6810:6820, 9869"
]
#*******************************************************************************
# API configuration attributes
#-------------------------------------------------------------------------------
# VM_SUBMIT_ON_HOLD: Forces VMs to be created on hold state instead of pending.
# Values: YES or NO.
# API_LIST_ORDER: Sets order (by ID) of elements in list API calls.
# Values: ASC (ascending order) or DESC (descending order)
#*******************************************************************************
#
#API_LIST_ORDER = "DESC"
#VM_SUBMIT_ON_HOLD = "NO"
#*******************************************************************************
@ -313,14 +323,6 @@ VXLAN_IDS = [
# vd KVM virtual disk
#
# DEFAULT_CDROM_DEVICE_PREFIX: Same as above but for CDROM devices.
#
# DEFAULT_IMAGE_PERSISTENT: Control the default value for the PERSISTENT
# attribute on image creation (oneimage clone, onevm disk-saveas). If blank
# images will inherit the persistent attribute from the base image.
#
# DEFAULT_IMAGE_PERSISTENT_NEW: Control the default value for the PERSISTENT
# attribute on image creation (oneimage create). By default images are no
# persistent if not set.
#*******************************************************************************
#DATASTORE_LOCATION = /var/lib/one/datastores

View File

@ -132,16 +132,21 @@ module CLIHelper
# Print header
def CLIHelper.print_header(str, underline=true)
if $stdout.tty?
scr_bold
scr_underline if underline
print str
scr_restore
print_tty_header(str, underline)
else
print str
end
puts
end
# Pretty print header
def CLIHelper.print_tty_header(str, underline=true)
scr_bold
scr_underline if underline
print str
scr_restore
end
module HashWithSearch
def dsearch(path)
stems=path.split('/')
@ -256,10 +261,18 @@ module CLIHelper
end
end
def print_tty_header
CLIHelper.print_tty_header(header_str)
puts
end
private
def print_table(data, options)
CLIHelper.print_header(header_str) if !options[:csv]
if !options[:csv] && !options[:noheader]
CLIHelper.print_header(header_str)
end
data ? print_data(data, options) : puts
end

View File

@ -16,6 +16,9 @@
require 'cli_helper'
require 'open3'
require 'io/console'
begin
require 'opennebula'
rescue Exception => e
@ -505,51 +508,243 @@ EOT
end
end
#-----------------------------------------------------------------------
# List pool functions
#-----------------------------------------------------------------------
def start_pager
pager = ENV['ONE_PAGER'] || 'less'
# Start pager, defaults to less
p_r, p_w = IO.pipe
lpid = fork do
$stdin.reopen(p_r)
p_r.close
p_w.close
Kernel.select [$stdin]
exec([pager, pager])
end
# Send listing to pager pipe
$stdout.close
$stdout = p_w.dup
p_w.close
p_r.close
return lpid
end
def stop_pager(lpid)
$stdout.close
Process.wait(lpid)
end
def print_page(pool, options)
page = nil
if options[:xml]
elements = 0
page = ""
pool.each {|e|
elements += 1
page << e.to_xml(true) << "\n"
}
else
pname = pool.pool_name
ename = pool.element_name
page = pool.to_hash
elems = page["#{pname}"]["#{ename}"]
if elems.class == Array
elements = elems.length
else
elements = 1
end
end
return elements, page
end
#-----------------------------------------------------------------------
# List the pool in table form, it uses pagination for interactive
# output
#-----------------------------------------------------------------------
def list_pool_table(table, pool, options, filter_flag)
if $stdout.isatty
size = $stdout.winsize[0] - 1
# ----------- First page, check if pager is needed -------------
rc = pool.get_page(size, 0)
ps = ""
return -1, rc.message if OpenNebula.is_error?(rc)
elements, hash = print_page(pool, options)
ppid = -1
if elements >= size
ppid = start_pager
end
table.show(hash, options)
if elements < size
return 0
end
# ------- Rest of the pages in the pool, piped to pager --------
current = size
options[:noheader] = true
loop do
rc = pool.get_page(size, current)
return -1, rc.message if OpenNebula.is_error?(rc)
current += size
elements, hash = print_page(pool, options)
table.show(hash, options)
$stdout.flush
break if elements < size
end
stop_pager(ppid)
else
array = pool.get_hash
return -1, array.message if OpenNebula.is_error?(array)
rname = self.class.rname
elements = array["#{rname}_POOL"][rname]
if options[:ids] && elements
elements.reject! do |element|
!options[:ids].include?(element['ID'].to_i)
end
end
table.show(array, options)
end
return 0
end
#-----------------------------------------------------------------------
# List pool in XML format, pagination is used in interactive output
#-----------------------------------------------------------------------
def list_pool_xml(pool, options, filter_flag)
if $stdout.isatty
size = $stdout.winsize[0] - 1
# ----------- First page, check if pager is needed -------------
rc = pool.get_page(size, 0)
ps = ""
return -1, rc.message if OpenNebula.is_error?(rc)
pname = pool.pool_name
elements, page = print_page(pool, options)
ppid = -1
if elements >= size
ppid = start_pager
end
puts "<#{pname}>"
puts page
if elements < size
puts "</#{pname}>"
return 0
end
# ------- Rest of the pages in the pool, piped to pager --------
current = size
loop do
rc = pool.get_page(size, current)
return -1, rc.message if OpenNebula.is_error?(rc)
current += size
elements, page = print_page(pool, options)
puts page
$stdout.flush
break if elements < size
end
puts "</#{pname}>"
stop_pager(ppid)
else
rc = pool.info
return -1, rc.message if OpenNebula.is_error?(rc)
puts pool.to_xml(true)
end
return 0
end
#-----------------------------------------------------------------------
# List pool table in top-like form
#-----------------------------------------------------------------------
def list_pool_top(table, pool, options)
table.top(options) {
array = pool.get_hash
return -1, array.message if OpenNebula.is_error?(array)
array
}
return 0
end
def list_pool(options, top=false, filter_flag=nil)
if options[:describe]
table = format_pool(options)
table = format_pool(options)
if options[:describe]
table.describe_columns
return 0
end
filter_flag ||= OpenNebula::Pool::INFO_ALL
pool = factory_pool(filter_flag)
pool = factory_pool(filter_flag)
if options[:xml]
# TODO: use paginated functions
rc=pool.info
return -1, rc.message if OpenNebula.is_error?(rc)
return 0, pool.to_xml(true)
if top
return list_pool_top(table, pool, options)
elsif options[:xml]
return list_pool_xml(pool, options, filter_flag)
else
table = format_pool(options)
if top
table.top(options) {
array=pool.get_hash
return -1, array.message if OpenNebula.is_error?(array)
array
}
else
array=pool.get_hash
return -1, array.message if OpenNebula.is_error?(array)
rname=self.class.rname
elements=array["#{rname}_POOL"][rname]
if options[:ids] && elements
elements.reject! do |element|
!options[:ids].include?(element['ID'].to_i)
end
end
table.show(array, options)
end
return 0
return list_pool_table(table, pool, options, filter_flag)
end
return 0
end
def show_resource(id, options)
@ -834,8 +1029,11 @@ EOT
end
end
def OpenNebulaHelper.time_to_str(time, print_seconds=true, print_hours=true, print_years=false)
value=time.to_i
def OpenNebulaHelper.time_to_str(time, print_seconds=true,
print_hours=true, print_years=false)
value = time.to_i
if value==0
value='-'
else

View File

@ -222,7 +222,8 @@ int GroupPool::drop(PoolObjectSQL * objsql, string& error_msg)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int GroupPool::dump(ostringstream& oss, const string& where, const string& limit)
int GroupPool::dump(ostringstream& oss, const string& where,
const string& limit, bool desc)
{
int rc;
string def_quota_xml;
@ -241,6 +242,11 @@ int GroupPool::dump(ostringstream& oss, const string& where, const string& limit
cmd << " ORDER BY oid";
if ( desc == true )
{
cmd << " DESC";
}
if ( !limit.empty() )
{
cmd << " LIMIT " << limit;

View File

@ -383,6 +383,7 @@ void OpenNebulaTemplate::set_conf_default()
# DB
# SCRIPTS_REMOTE_DIR
# VM_SUBMIT_ON_HOLD
# API_LIST_ORDER
# VNC_PORTS
#*******************************************************************************
*/
@ -401,6 +402,7 @@ void OpenNebulaTemplate::set_conf_default()
set_conf_single("LISTEN_ADDRESS", "0.0.0.0");
set_conf_single("SCRIPTS_REMOTE_DIR", "/var/tmp/one");
set_conf_single("VM_SUBMIT_ON_HOLD", "NO");
set_conf_single("API_LIST_ORDER", "DESC");
//DB CONFIGURATION
vvalue.insert(make_pair("BACKEND","sqlite"));

View File

@ -24,6 +24,9 @@ module OpenNebula
include Enumerable
alias_method :each_with_xpath, :each
attr_reader :pool_name
attr_reader :element_name
PAGINATED_POOLS=%w{VM_POOL IMAGE_POOL TEMPLATE_POOL VN_POOL
DOCUMENT_POOL SECGROUP_POOL}
@ -132,12 +135,13 @@ module OpenNebula
# xml_method:: _String_ the name of the XML-RPC method
# args:: _Array_ with additional arguments for the info call
# [return] nil in case of success or an Error object
def xmlrpc_info(xml_method,*args)
rc = @client.call(xml_method,*args)
def xmlrpc_info(xml_method, *args)
rc = @client.call(xml_method, *args)
if !OpenNebula.is_error?(rc)
initialize_xml(rc,@pool_name)
rc = nil
initialize_xml(rc, @pool_name)
rc = nil
end
return rc
@ -179,14 +183,17 @@ module OpenNebula
if OpenNebula.pool_page_size && allow_paginated &&
( ( size && size >= 2 ) || !size )
size = OpenNebula.pool_page_size if !size
hash=info_paginated(size)
hash = info_paginated(size)
return hash if OpenNebula.is_error?(hash)
{ @pool_name => { @element_name => hash } }
else
rc=info
rc = info
return rc if OpenNebula.is_error?(rc)
to_hash
end
end
@ -195,14 +202,15 @@ module OpenNebula
#
# size:: _Integer_ size of each page
def info_paginated(size)
array=Array.new
current=0
array = Array.new
current = 0
parser=ParsePoolSax.new(@pool_name, @element_name)
parser = ParsePoolSax.new(@pool_name, @element_name)
while true
a=@client.call("#{@pool_name.delete('_').downcase}.info",
@user_id, current, -size, -1)
a = @client.call("#{@pool_name.delete('_').downcase}.info",
@user_id, current, -size, -1)
return a if OpenNebula.is_error?(a)
a_array=parser.parse(a)
@ -214,9 +222,30 @@ module OpenNebula
end
array.compact!
array=nil if array.length == 0
array = nil if array.length == 0
array
end
# Gets a hash from a info page from pool
# size:: nil => default page size
# > 0 => page size
# current first element of the page
# hash:: return page as a hash
def get_page(size, current)
rc = nil
if PAGINATED_POOLS.include?(@pool_name)
size = OpenNebula.pool_page_size if (!size || size == 0)
rc = @client.call("#{@pool_name.delete('_').downcase}.info",
@user_id, current, -size, -1)
initialize_xml(rc, @pool_name)
else
rc = info
end
return rc
end
end
end

View File

@ -430,30 +430,5 @@ module OpenNebula
return attr
end
end
# The XMLUtilsPool module provides an abstraction of the underlying
# XML parser engine. It provides XML-related methods for the Pools
class XMLPool < XMLElement
def initialize(xml=nil)
super(xml)
end
#Executes the given block for each element of the Pool
#block:: _Block_
def each_element(block)
if NOKOGIRI
@xml.xpath(
"#{@element_name}").each {|pelem|
block.call self.factory(pelem)
}
else
@xml.elements.each(
"#{@element_name}") {|pelem|
block.call self.factory(pelem)
}
end
end
end
end

View File

@ -214,7 +214,7 @@ PoolObjectSQL * PoolSQL::get(const string& name, int ouid)
/* -------------------------------------------------------------------------- */
int PoolSQL::dump(ostringstream& oss, const string& elem_name, const char* table,
const string& where, const string& limit)
const string& where, const string& limit, bool desc)
{
ostringstream cmd;
@ -227,6 +227,11 @@ int PoolSQL::dump(ostringstream& oss, const string& elem_name, const char* table
cmd << " ORDER BY oid";
if ( desc == true )
{
cmd << " DESC";
}
if ( !limit.empty() )
{
cmd << " LIMIT " << limit;

View File

@ -438,8 +438,11 @@ void RequestManagerPoolInfoFilter::dump(
const string& or_clause)
{
ostringstream oss;
string where_string, limit_clause;
int rc;
std::string where_string, limit_clause;
std::string desc;
int rc;
if ( filter_flag < GROUP )
{
@ -466,7 +469,11 @@ void RequestManagerPoolInfoFilter::dump(
oss.str("");
}
rc = pool->dump(oss, where_string, limit_clause);
Nebula::instance().get_configuration_attribute(att.uid, att.gid,
"API_LIST_ORDER", desc);
rc = pool->dump(oss, where_string, limit_clause,
one_util::toupper(desc) == "DESC");
if ( rc != 0 )
{
@ -528,10 +535,14 @@ void VirtualNetworkPoolInfo::request_execute(
/* ---------------------------------------------------------------------- */
/* Get the VNET pool */
/* ---------------------------------------------------------------------- */
ostringstream pool_oss;
std::string desc;
int rc = pool->dump(pool_oss, where_string.str(), limit_clause.str());
Nebula::instance().get_configuration_attribute(att.uid, att.gid,
"API_LIST_ORDER", desc);
int rc = pool->dump(pool_oss, where_string.str(), limit_clause.str(),
one_util::toupper(desc) == "DESC");
if ( rc != 0 )
{

View File

@ -1275,7 +1275,8 @@ int UserPool::authorize(AuthRequest& ar)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int UserPool::dump(ostringstream& oss, const string& where, const string& limit)
int UserPool::dump(ostringstream& oss, const string& where, const string& limit,
bool desc)
{
int rc;
string def_quota_xml;
@ -1294,6 +1295,11 @@ int UserPool::dump(ostringstream& oss, const string& where, const string& limit)
cmd << " ORDER BY oid";
if ( desc == true )
{
cmd << " DESC";
}
if ( !limit.empty() )
{
cmd << " LIMIT " << limit;