diff --git a/include/History.h b/include/History.h
index e124ec7a2e..952320e62c 100644
--- a/include/History.h
+++ b/include/History.h
@@ -45,7 +45,8 @@ public:
int hid,
const string& hostname,
const string& vmm,
- const string& vnm);
+ const string& vnm,
+ const string& vm_info);
~History(){};
@@ -69,9 +70,8 @@ private:
// ----------------------------------------
// DataBase implementation variables
// ----------------------------------------
-
static const char * table;
-
+
static const char * db_names;
static const char * db_bootstrap;
@@ -104,6 +104,8 @@ private:
MigrationReason reason;
+ string vm_info;
+
// -------------------------------------------------------------------------
// Non-persistent history fields
// -------------------------------------------------------------------------
@@ -169,6 +171,23 @@ private:
*/
int select_cb(void *nil, int num, char **values, char **names);
+ /**
+ * Function to print the History object into a string in
+ * XML format, to be stored in the DB. It includes the VM template info
+ * @param xml the resulting XML string
+ * @return a reference to the generated string
+ */
+ string& to_db_xml(string& xml) const;
+
+ /**
+ * Function to print the History object into a string in
+ * XML format. The VM info can be optionally included
+ * @param xml the resulting XML string
+ * @param database If it is true, the TEMPLATE element will be included
+ * @return a reference to the generated string
+ */
+ string& to_xml(string& xml, bool database) const;
+
/**
* Rebuilds the object from an xml node
* @param node The xml node pointer
diff --git a/include/PoolSQL.h b/include/PoolSQL.h
index c127d075e6..c6a4a262df 100644
--- a/include/PoolSQL.h
+++ b/include/PoolSQL.h
@@ -154,6 +154,47 @@ public:
*/
virtual int dump(ostringstream& oss, const string& where) = 0;
+ // -------------------------------------------------------------------------
+ // Function to generate dump filters
+ // -------------------------------------------------------------------------
+
+ /**
+ * Creates a filter for those objects (oids) or objects owned by a given
+ * group that an user can access based on the ACL rules
+ * @param uid the user id
+ * @param gid the group id
+ * @param auth_object object type
+ * @param all returns if the user can access all objects
+ * @param filter the resulting filter string
+ */
+ static void acl_filter(int uid,
+ int gid,
+ PoolObjectSQL::ObjectType auth_object,
+ bool& all,
+ string& filter);
+ /**
+ * Creates a filter for the objects owned by a given user/group
+ * @param uid the user id
+ * @param gid the group id
+ * @param filter_flag query type (ALL, MINE, GROUP)
+ * @param all user can access all objects
+ * @param filter the resulting filter string
+ */
+ static void usr_filter(int uid,
+ int gid,
+ int filter_flag,
+ bool all,
+ const string& acl_str,
+ string& filter);
+ /**
+ * Creates a filter for a given set of objects based on their id
+ * @param start_id first id
+ * @param end_id last id
+ * @param filter the resulting filter string
+ */
+ static void oid_filter(int start_id,
+ int end_id,
+ string& filter);
protected:
/**
@@ -182,8 +223,23 @@ protected:
*
* @return 0 on success
*/
- int dump(ostringstream& oss, const string& elem_name,
- const char * table, const string& where);
+ int dump(ostringstream& oss,
+ const string& elem_name,
+ const char * table,
+ const string& where);
+
+ /**
+ * Dumps the output of the custom sql query into an xml
+ *
+ * @param oss The output stream to dump the xml contents
+ * @param root_elem_name Name of the root xml element name
+ * @param sql_query The SQL query to execute
+ *
+ * @return 0 on success
+ */
+ int dump(ostringstream& oss,
+ const string& root_elem_name,
+ ostringstream& sql_query);
/* ---------------------------------------------------------------------- */
/* Interface to access the lastOID assigned by the pool */
diff --git a/include/RequestManagerPoolInfoFilter.h b/include/RequestManagerPoolInfoFilter.h
index 2270f7c471..08d3459f2c 100644
--- a/include/RequestManagerPoolInfoFilter.h
+++ b/include/RequestManagerPoolInfoFilter.h
@@ -29,6 +29,16 @@ using namespace std;
class RequestManagerPoolInfoFilter: public Request
{
+public:
+ /** Specify all objects the user has right to USE (-2) */
+ static const int ALL;
+
+ /** Specify user's objects in the pool (-3) */
+ static const int MINE;
+
+ /** Specify user's + group objects (-1) */
+ static const int MINE_GROUP;
+
protected:
RequestManagerPoolInfoFilter(const string& method_name,
const string& help,
@@ -40,27 +50,26 @@ protected:
/* -------------------------------------------------------------------- */
- /** Specify all objects the user has right to USE (-2) */
- static const int ALL;
-
- /** Specify user's objects in the pool (-3) */
- static const int MINE;
-
- /** Specify user's + group objects (-1) */
- static const int MINE_GROUP;
-
- /* -------------------------------------------------------------------- */
-
virtual void request_execute(
xmlrpc_c::paramList const& paramList, RequestAttributes& att);
/* -------------------------------------------------------------------- */
- void dump(RequestAttributes& att,
+ void where_filter(RequestAttributes& att,
+ int filter_flag,
+ int start_id,
+ int end_id,
+ const string& and_clause,
+ const string& or_clause,
+ string& where_string);
+
+ /* -------------------------------------------------------------------- */
+
+ void dump(RequestAttributes& att,
int filter_flag,
- int start_id,
+ int start_id,
int end_id,
- const string& and_clause,
+ const string& and_clause,
const string& or_clause);
};
@@ -98,6 +107,31 @@ public:
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
+class VirtualMachinePoolAccounting : public RequestManagerPoolInfoFilter
+{
+public:
+
+ VirtualMachinePoolAccounting():
+ RequestManagerPoolInfoFilter("VirtualMachinePoolAccounting",
+ "Returns the virtual machine history records",
+ "A:siii")
+ {
+ Nebula& nd = Nebula::instance();
+ pool = nd.get_vmpool();
+ auth_object = PoolObjectSQL::VM;
+ };
+
+ ~VirtualMachinePoolAccounting(){};
+
+ /* -------------------------------------------------------------------- */
+
+ void request_execute(
+ xmlrpc_c::paramList const& paramList, RequestAttributes& att);
+};
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+
class TemplatePoolInfo : public RequestManagerPoolInfoFilter
{
public:
diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h
index be2ba87c0f..494b2a342a 100644
--- a/include/VirtualMachine.h
+++ b/include/VirtualMachine.h
@@ -122,7 +122,10 @@ public:
* @param xml the resulting XML string
* @return a reference to the generated string
*/
- string& to_xml(string& xml) const;
+ string& to_xml(string& xml) const
+ {
+ return to_xml_extended(xml, 1);
+ }
/**
* Function to print the VirtualMachine object into a string in
@@ -130,7 +133,10 @@ public:
* @param xml the resulting XML string
* @return a reference to the generated string
*/
- string& to_xml_extended(string& xml) const;
+ string& to_xml_extended(string& xml) const
+ {
+ return to_xml_extended(xml, 2);
+ }
/**
* Rebuilds the object from an xml formatted string
@@ -156,7 +162,7 @@ public:
/**
* Updates VM dynamic information (usage counters).
- * @param _memory used by the VM (total)
+ * @param _memory Kilobytes used by the VM (total)
* @param _cpu used by the VM (rate)
* @param _net_tx transmitted bytes (total)
* @param _net_tx received bytes (total)
@@ -199,7 +205,7 @@ public:
/**
* Sets the VM exit time
- * @param _et VM exit time (when it arraived DONE/FAILED states)
+ * @param _et VM exit time (when it arrived DONE/FAILED states)
*/
void set_exit_time(time_t et)
{
@@ -428,6 +434,22 @@ public:
history->stime=_stime;
};
+ /**
+ * Sets VM info (with monitoring info) in the history record
+ */
+ void set_vm_info()
+ {
+ to_xml_extended(history->vm_info, 0);
+ };
+
+ /**
+ * Sets VM info (with monitoring info) in the previous history record
+ */
+ void set_previous_vm_info()
+ {
+ to_xml_extended(previous_history->vm_info, 0);
+ };
+
/**
* Sets end time of a VM.
* @param _etime time when the VM finished
@@ -757,7 +779,7 @@ private:
string deploy_id;
/**
- * Memory in Megabytes used by the VM
+ * Memory in Kilobytes used by the VM
*/
int memory;
@@ -767,12 +789,12 @@ private:
int cpu;
/**
- * Network usage, transmitted Kilobytes
+ * Network usage, transmitted bytes
*/
int net_tx;
/**
- * Network usage, received Kilobytes
+ * Network usage, received bytes
*/
int net_rx;
@@ -916,10 +938,13 @@ private:
* Function that renders the VM in XML format optinally including
* extended information (all history records)
* @param xml the resulting XML string
- * @param extended include additional info if true
+ * @param n_history Number of history records to include:
+ * 0: none
+ * 1: the last one
+ * 2: all
* @return a reference to the generated string
*/
- string& to_xml_extended(string& xml, bool extended) const;
+ string& to_xml_extended(string& xml, int n_history) const;
protected:
@@ -939,7 +964,7 @@ protected:
// *************************************************************************
// DataBase implementation
// *************************************************************************
-
+
static const char * table;
static const char * db_names;
diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h
index 7e3ea7e6e2..664da7fdb6 100644
--- a/include/VirtualMachinePool.h
+++ b/include/VirtualMachinePool.h
@@ -143,8 +143,20 @@ public:
int dump(ostringstream& oss, const string& where)
{
return PoolSQL::dump(oss, "VM_POOL", VirtualMachine::table, where);
- }
+ };
+ /**
+ * Dumps the VM accounting information in XML format. A filter can be also
+ * added to the query as well as a time frame.
+ * @param oss the output stream to dump the pool contents
+ * @param where filter for the objects, defaults to all
+ *
+ * @return 0 on success
+ */
+ int dump_acct(ostringstream& oss,
+ const string& where,
+ int time_start,
+ int time_end);
private:
/**
* Factory method to produce VM objects
diff --git a/install.sh b/install.sh
index c668e02297..083c65d0fd 100755
--- a/install.sh
+++ b/install.sh
@@ -883,6 +883,8 @@ ONEDB_MIGRATOR_FILES="src/onedb/2.0_to_2.9.80.rb \
src/onedb/3.2.1_to_3.3.0.rb \
src/onedb/3.3.0_to_3.3.80.rb \
src/onedb/3.3.80_to_3.4.0.rb \
+ src/onedb/3.4.0_to_3.4.1.rb \
+ src/onedb/3.4.1_to_3.5.80.rb \
src/onedb/onedb.rb \
src/onedb/onedb_backend.rb"
diff --git a/share/doc/xsd/acct.xsd b/share/doc/xsd/acct.xsd
new file mode 100644
index 0000000000..fe210dc829
--- /dev/null
+++ b/share/doc/xsd/acct.xsd
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/share/doc/xsd/datastore.xsd b/share/doc/xsd/datastore.xsd
index 0573cf31e2..c1f5dfac98 100644
--- a/share/doc/xsd/datastore.xsd
+++ b/share/doc/xsd/datastore.xsd
@@ -28,6 +28,7 @@
+
diff --git a/share/doc/xsd/image.xsd b/share/doc/xsd/image.xsd
index e5f1881b22..8f664824bc 100644
--- a/share/doc/xsd/image.xsd
+++ b/share/doc/xsd/image.xsd
@@ -25,6 +25,7 @@
+
diff --git a/share/doc/xsd/vm.xsd b/share/doc/xsd/vm.xsd
index 039f4a3d75..576790c2a4 100644
--- a/share/doc/xsd/vm.xsd
+++ b/share/doc/xsd/vm.xsd
@@ -26,14 +26,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -42,21 +86,28 @@
+
-
-
+
+
diff --git a/share/etc/oned.conf b/share/etc/oned.conf
index 0bf1cd0492..2f4c5d807a 100644
--- a/share/etc/oned.conf
+++ b/share/etc/oned.conf
@@ -298,7 +298,7 @@ TM_MAD = [
DATASTORE_MAD = [
executable = "one_datastore",
- arguments = "-t 15 -d fs,vmware,iscsi"
+ arguments = "-t 15 -d fs,vmware,iscsi,lvm"
]
#*******************************************************************************
diff --git a/src/cli/oneacct b/src/cli/oneacct
index a9a3e52fe6..a9101f5bc1 100755
--- a/src/cli/oneacct
+++ b/src/cli/oneacct
@@ -1,25 +1,20 @@
#!/usr/bin/env ruby
-# --------------------------------------------------------------------------
-# Copyright 2010-2012, C12G Labs S.L.
-#
-# This file is part of OpenNebula addons.
-#
-# OpenNebula addons are free software: you can redistribute it
-# and/or modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation, either version 3 of
-# the License, or the hope That it will be useful, but (at your
-# option) any later version.
-#
-# OpenNebula addons are distributed in WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License
-# along with OpenNebula addons. If not, see
-#
-# --------------------------------------------------------------------------
+# -------------------------------------------------------------------------- #
+# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); you may #
+# not use this file except in compliance with the License. You may obtain #
+# a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+#--------------------------------------------------------------------------- #
ONE_LOCATION=ENV["ONE_LOCATION"]
@@ -35,7 +30,6 @@ $: << RUBY_LIB_LOCATION+"/cli"
require 'rubygems'
-require 'acct/oneacct'
require 'cli/one_helper'
require 'cli/command_parser'
require 'json'
@@ -43,164 +37,171 @@ require 'json'
require 'optparse'
require 'optparse/time'
-REG_DATE=/((\d{4})\/)?(\d\d?)(\/(\d\d?))?/
-REG_TIME=/(\d\d?):(\d\d?)(:(\d\d?))?/
-
class AcctHelper
- def format_vm(options=nil)
- table = CLIHelper::ShowTable.new(nil, nil) do
- column :VMID, "VM ID", :size=>4 do |d|
- d[:vmid]
+ def initialize(client)
+ @client = client
+ end
+
+=begin
+ List of child elements
+
+ OID
+ SEQ
+ HOSTNAME
+ HID
+ STIME
+ ETIME
+ VMMMAD
+ VNMMAD
+ PSTIME
+ PETIME
+ RSTIME
+ RETIME
+ ESTIME
+ EETIME
+ REASON
+=end
+
+ def list_history(data)
+ table = CLIHelper::ShowTable.new(nil, self) do
+ column :VID, "Virtual Machine ID", :size=>4 do |d|
+ d["OID"]
end
- column :MEMORY, "Consumed memory", :right, :size=>8 do |d|
- OpenNebulaHelper.unit_to_str(
- d[:slices].first[:mem]*1024,
- {})
+ column :SEQ, "History record sequence number", :size=>3 do |d|
+ d["SEQ"]
end
- column :CPU, "Group of the User", :right, :size=>8 do |d|
- d[:slices].first[:cpu]
+ column :HOSTNAME, "Host name", :size=>15 do |d|
+ d["HOSTNAME"]
end
- column :NETRX, "Group of the User", :right, :size=>10 do |d|
- OpenNebulaHelper.unit_to_str(
- d[:network][:net_rx].to_i/1024.0,
- {})
+ column :REASON, "VM state change reason", :size=>4 do |d|
+ VirtualMachine.get_reason d["REASON"]
end
- column :NETTX, "Group of the User", :right, :size=>10 do |d|
- OpenNebulaHelper.unit_to_str(
- d[:network][:net_tx].to_i/1024.0,
- {})
+ column :START_TIME, "Start time", :size=>14 do |d|
+ OpenNebulaHelper.time_to_str(d['STIME'])
end
- column :TIME, "Group of the User", :right, :size=>15 do |d|
- OpenNebulaHelper.period_to_str(d[:time])
+ column :END_TIME, "End time", :size=>14 do |d|
+ OpenNebulaHelper.time_to_str(d['ETIME'])
end
- default :VMID, :MEMORY, :CPU, :NETRX, :NETTX, :TIME
+ column :MEMORY, "Assigned memory", :right, :size=>6 do |d|
+ OpenNebulaHelper.unit_to_str(d["VM/TEMPLATE/MEMORY"].to_i, {}, 'M')
+ end
+
+ column :CPU, "Number of CPUs", :right, :size=>3 do |d|
+ d["VM/TEMPLATE/CPU"]
+ end
+
+ column :NET_RX, "Data received from the network", :right, :size=>6 do |d|
+ # NET is measured in bytes, unit_to_str expects KBytes
+ OpenNebulaHelper.unit_to_str(d["VM/NET_RX"].to_i / 1024.0, {})
+ end
+
+ column :NET_TX, "Data sent to the network", :right, :size=>6 do |d|
+ # NET is measured in bytes, unit_to_str expects KBytes
+ OpenNebulaHelper.unit_to_str(d["VM/NET_TX"].to_i / 1024.0, {})
+ end
+
+ default :VID, :HOSTNAME, :REASON, :START_TIME, :END_TIME, :MEMORY, :CPU, :NET_RX, :NET_TX
end
- table
+ table.show(data)
end
- def list_vms(data)
- format_vm().show(data)
- end
+public
+ def list_users(xml_info, options=nil)
- def list_users(filters)
- a=gen_accounting(filters)
+ xmldoc = XMLElement.new
+ xmldoc.initialize_xml(xml_info, 'HISTORY_RECORDS')
- a.each do |user, data|
+ uids = xmldoc.retrieve_elements('HISTORY/VM/UID')
+ if uids.nil?
+ puts "No records found."
+ exit 0
+ end
+
+ uids.uniq!
+
+ history_elems = []
+
+ uids.each do |uid|
CLIHelper.scr_bold
CLIHelper.scr_underline
- puts "# User #{user}"
+ # TODO: username?
+ puts "# User #{uid} "
CLIHelper.scr_restore
puts
- vms=data[:vms].map do |k, v|
- v
- end
+ history_elems.clear
- self.list_vms(vms)
+ vm_ids = xmldoc.retrieve_elements("HISTORY/VM[UID=#{uid}]/ID")
+ vm_ids.uniq!
- puts
- puts
+ vm_ids.each do |vid|
- end
- end
-
- def gen_accounting(filters)
- acct=AcctClient.new(filters)
- acct.account()
- end
-
- def gen_json(filters)
- begin
- require 'json'
- rescue LoadError
- STDERR.puts "JSON gem is needed to give the result in this format"
- exit(-1)
- end
-
- acct=gen_accounting(filters)
- acct.to_json
- end
-
- def xml_tag(tag, value)
- "<#{tag}>#{value}#{tag}>\n"
- end
-
- def gen_xml(filters)
- acct=gen_accounting(filters)
-
- xml=""
-
- acct.each do |user, data|
- xml<<"\n"
-
- data[:vms].each do |vmid, vm|
- xml<<" \n"
-
- xml<<" "<\n"
-
- slice.each do |key, value|
- xml<<" "<\n"
+ if ( options[:split] )
+ history_elems.clear
end
- xml<<" \n"
+ xmldoc.each("HISTORY[OID=#{vid}]") do |history|
+ history_elems << history
+ end
+
+ if ( options[:split] )
+ list_history(history_elems)
+ puts
+ end
end
- xml<<"\n"
+ if ( !options[:split] )
+ list_history(history_elems)
+ puts
+ end
end
-
- xml
end
end
-@options=Hash.new
+options = Hash.new
-@options[:format]=:table
+options[:format] = :table
-opts=OptionParser.new do |opts|
+opts = OptionParser.new do |opts|
opts.on('-s', '--start TIME', Time,
'Start date and time to take into account') do |ext|
- @options[:start]=ext
+ options[:start]=ext
end
opts.on("-e", "--end TIME", Time,
"End date and time" ) do |ext|
- @options[:end]=ext
+ options[:end]=ext
end
+ # TODO: Allow username
opts.on("-u", "--user user", Integer,
"User id to make accounting" ) do |ext|
- @options[:user]=ext.to_i
+ options[:user]=ext.to_i
end
opts.on("-j", "--json",
"Output in json format" ) do |ext|
- @options[:format]=:json
+ options[:format]=:json
end
opts.on("-x", "--xml",
"Output in xml format" ) do |ext|
- @options[:format]=:xml
+ options[:format]=:xml
+ end
+
+ opts.on("--split",
+ "Split the output in a table for each VM" ) do |ext|
+ options[:split]=ext
end
opts.on()
@@ -215,27 +216,68 @@ rescue OptionParser::ParseError => e
end
-acct_helper=AcctHelper.new
+client = OpenNebula::Client.new
+
+acct_helper = AcctHelper.new(client)
+
+time_start = -1
+time_end = -1
+filter_flag = VirtualMachinePool::INFO_ALL
+
+time_start = options[:start].to_i if options[:start]
+time_end = options[:end].to_i if options[:end]
+filter_flag = options[:user].to_i if options[:user]
-filters=Hash.new
+ret = client.call("vmpool.accounting",
+ filter_flag,
+ time_start,
+ time_end)
-filters[:start]=@options[:start].to_i if @options[:start]
-filters[:end]=@options[:end].to_i if @options[:end]
-filters[:user]=@options[:user].to_i if @options[:user]
-
-
-case @options[:format]
-when :table
- acct_helper.list_users(filters)
-when :json
- puts acct_helper.gen_json(filters)
-when :xml
- puts acct_helper.gen_xml(filters)
+if OpenNebula.is_error?(ret)
+ puts ret.message
+ exit -1
end
+case options[:format]
+when :table
+ if ( time_start != -1 or time_end != -1 )
+ print "Showing active history records from "
+ CLIHelper.scr_bold
+ if ( time_start != -1 )
+ print Time.at(time_start).to_s
+ else
+ print "-"
+ end
+ CLIHelper.scr_restore
+ print " to "
+
+ CLIHelper.scr_bold
+
+ if ( time_end != -1 )
+ print Time.at(time_end).to_s
+ else
+ print "-"
+ end
+
+ CLIHelper.scr_restore
+ puts
+ puts
+ end
+
+ acct_helper.list_users(ret, options)
+
+when :xml
+ puts ret
+
+when :json
+ xmldoc = XMLElement.new
+ xmldoc.initialize_xml(ret, 'HISTORY_RECORDS')
+ puts xmldoc.to_hash.to_json
+
+end
diff --git a/src/cloud/ec2/bin/econe-server b/src/cloud/ec2/bin/econe-server
index 1327de4ed1..976175ee79 100755
--- a/src/cloud/ec2/bin/econe-server
+++ b/src/cloud/ec2/bin/econe-server
@@ -34,9 +34,12 @@ fi
setup()
{
- eval `grep ^IMAGE_DIR= $ECONE_ETC`
- export TMPDIR=$IMAGE_DIR/tmp
- mkdir -p $TMPDIR
+ TMPDIR=$(grep ^:tmpdir: $ECONE_ETC|awk '{print $2}')
+
+ if [ -n "$TMPDIR" ]; then
+ export TMPDIR
+ mkdir -p $TMPDIR
+ fi
if [ -f $ECONE_LOCK_FILE ]; then
if [ -f $ECONE_PID ]; then
diff --git a/src/cloud/ec2/etc/econe.conf b/src/cloud/ec2/etc/econe.conf
index 35de897481..d8329b9f52 100644
--- a/src/cloud/ec2/etc/econe.conf
+++ b/src/cloud/ec2/etc/econe.conf
@@ -18,11 +18,14 @@
# Server Configuration
#############################################################
+# Directory to store temp files when uploading images
+:tmpdir: /var/tmp/one
+
# OpenNebula sever contact information
:one_xmlrpc: http://localhost:2633/RPC2
# Host and port where econe server will run
-:server: localhost
+:host: localhost
:port: 4567
# SSL proxy that serves the API (set if is being used)
diff --git a/src/cloud/ec2/lib/econe-server.rb b/src/cloud/ec2/lib/econe-server.rb
index 24601cefc9..953a11ffa0 100644
--- a/src/cloud/ec2/lib/econe-server.rb
+++ b/src/cloud/ec2/lib/econe-server.rb
@@ -79,7 +79,14 @@ set :config, conf
include CloudLogger
enable_logging EC2_LOG, settings.config[:debug_level].to_i
-if CloudServer.is_port_open?(settings.config[:server],
+if settings.config[:server]
+ settings.config[:host] ||= settings.config[:server]
+ warning = "Warning: :server: configuration parameter has been deprecated."
+ warning << " Use :host: instead."
+ settings.logger.warn warning
+end
+
+if CloudServer.is_port_open?(settings.config[:host],
settings.config[:port])
settings.logger.error {
"Port #{settings.config[:port]} busy, please shutdown " <<
@@ -88,7 +95,7 @@ if CloudServer.is_port_open?(settings.config[:server],
exit -1
end
-set :bind, settings.config[:server]
+set :bind, settings.config[:host]
set :port, settings.config[:port]
begin
@@ -108,8 +115,8 @@ if conf[:ssl_server]
econe_port = uri.port
econe_path = uri.path
else
- econe_host = conf[:server]
- econe_port = conf[:port]
+ econe_host = settings.config[:host]
+ econe_port = settings.config[:port]
econe_path = '/'
end
diff --git a/src/cloud/occi/bin/occi-server b/src/cloud/occi/bin/occi-server
index 72625a1d61..812407b162 100755
--- a/src/cloud/occi/bin/occi-server
+++ b/src/cloud/occi/bin/occi-server
@@ -34,9 +34,12 @@ fi
setup()
{
- eval `grep ^IMAGE_DIR= $OCCI_ETC `
- export TMPDIR=$IMAGE_DIR/tmp
+ TMPDIR=$(grep ^:tmpdir: $OCCI_ETC|awk '{print $2}')
+
+ if [ -n "$TMPDIR" ]; then
+ export TMPDIR
mkdir -p $TMPDIR
+ fi
if [ -f $OCCI_LOCK_FILE ]; then
if [ -f $OCCI_PID ]; then
diff --git a/src/cloud/occi/etc/occi-server.conf b/src/cloud/occi/etc/occi-server.conf
index f041e6d83e..09a6c446d8 100644
--- a/src/cloud/occi/etc/occi-server.conf
+++ b/src/cloud/occi/etc/occi-server.conf
@@ -18,6 +18,9 @@
# Server configuration
#############################################################
+# Directory to store temp files when uploading images
+:tmpdir: /var/tmp/one
+
# OpenNebula sever contact information
:one_xmlrpc: http://localhost:2633/RPC2
diff --git a/src/cloud/occi/lib/occi-server.rb b/src/cloud/occi/lib/occi-server.rb
index 183ef31c88..9225496094 100644
--- a/src/cloud/occi/lib/occi-server.rb
+++ b/src/cloud/occi/lib/occi-server.rb
@@ -92,7 +92,14 @@ use Rack::Session::Pool, :key => 'occi'
set :public_folder, Proc.new { File.join(root, "ui/public") }
set :views, settings.root + '/ui/views'
-if CloudServer.is_port_open?(settings.config[:server],
+if settings.config[:server]
+ settings.config[:host] ||= settings.config[:server]
+ warning = "Warning: :server: configuration parameter has been deprecated."
+ warning << " Use :host: instead."
+ settings.logger.warn warning
+end
+
+if CloudServer.is_port_open?(settings.config[:host],
settings.config[:port])
settings.logger.error {
"Port #{settings.config[:port]} busy, please shutdown " <<
@@ -101,20 +108,10 @@ if CloudServer.is_port_open?(settings.config[:server],
exit -1
end
-host = settings.config[:host] || settings.config[:server]
-set :bind, host
-
-if settings.config[:server]
- warning = "Warning: :server: configuration parameter has been deprecated."
- warning << " Use :host: instead."
- settings.logger.error warning
-end
-
+set :bind, settings.config[:host]
set :port, settings.config[:port]
-
-
# Create CloudAuth
begin
ENV["ONE_CIPHER_AUTH"] = OCCI_AUTH
diff --git a/src/datastore_mad/remotes/vmware/cp b/src/datastore_mad/remotes/vmware/cp
index bb4995a5ef..a0e892d153 100755
--- a/src/datastore_mad/remotes/vmware/cp
+++ b/src/datastore_mad/remotes/vmware/cp
@@ -76,8 +76,10 @@ case $SRC in
exec_and_log "cp -rf $SRC $DST" "Error copying $SRC to $DST"
+
if [ ! -f $DST/disk.vmdk ]; then
- BASE_DISK_FILE=`ls $DST | grep -v '.*-s[0-9]*\.vmdk'`
+ BASE_DISK_FILE=`ls $DST | grep -v '\-\(flat\|delta\|s[0-9]*\)\.vmdk$'`
+
exec_and_log "mv -f $DST/$BASE_DISK_FILE $DST/disk.vmdk" \
"Error renaming disk file $BASE_DISK_FILE to disk.vmdk"
diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc
index 234e686a58..3e6d0c2b9a 100644
--- a/src/lcm/LifeCycleActions.cc
+++ b/src/lcm/LifeCycleActions.cc
@@ -615,6 +615,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm)
vmpool->update(vm);
vm->set_etime(the_time);
+ vm->set_vm_info();
vm->set_reason(History::USER);
vm->get_requirements(cpu,mem,disk);
@@ -650,6 +651,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm)
vmpool->update_history(vm);
vm->set_previous_etime(the_time);
+ vm->set_previous_vm_info();
vm->set_previous_running_etime(the_time);
vm->set_previous_reason(History::USER);
vmpool->update_previous_history(vm);
@@ -680,6 +682,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm)
vmpool->update_history(vm);
vm->set_previous_etime(the_time);
+ vm->set_previous_vm_info();
vm->set_previous_running_etime(the_time);
vm->set_previous_reason(History::USER);
vmpool->update_previous_history(vm);
diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc
index 11cf2bd7be..0165d3ec8d 100644
--- a/src/lcm/LifeCycleStates.cc
+++ b/src/lcm/LifeCycleStates.cc
@@ -49,6 +49,8 @@ void LifeCycleManager::save_success_action(int vid)
vm->set_previous_etime(the_time);
+ vm->set_previous_vm_info();
+
vm->set_previous_running_etime(the_time);
vm->set_previous_reason(History::USER);
@@ -84,6 +86,8 @@ void LifeCycleManager::save_success_action(int vid)
vm->set_etime(the_time);
+ vm->set_vm_info();
+
vm->set_reason(History::STOP_RESUME);
vmpool->update_history(vm);
@@ -162,6 +166,8 @@ void LifeCycleManager::save_failure_action(int vid)
vm->set_etime(the_time);
+ vm->set_vm_info();
+
vm->set_reason(History::ERROR);
vmpool->update_history(vm);
@@ -172,6 +178,8 @@ void LifeCycleManager::save_failure_action(int vid)
vm->set_previous_etime(the_time);
+ vm->set_previous_vm_info();
+
vm->set_previous_running_etime(the_time);
vm->set_previous_reason(History::USER);
@@ -251,6 +259,8 @@ void LifeCycleManager::deploy_success_action(int vid)
vm->set_previous_etime(the_time);
+ vm->set_previous_vm_info();
+
vm->set_previous_running_etime(the_time);
vm->set_previous_reason(History::USER);
@@ -304,10 +314,14 @@ void LifeCycleManager::deploy_failure_action(int vid)
vm->set_etime(the_time);
+ vm->set_vm_info();
+
vm->set_reason(History::ERROR);
vm->set_previous_etime(the_time);
+ vm->set_previous_vm_info();
+
vm->set_previous_running_etime(the_time);
vm->set_previous_reason(History::USER);
@@ -554,6 +568,8 @@ void LifeCycleManager::epilog_success_action(int vid)
vm->set_etime(the_time);
+ vm->set_vm_info();
+
vmpool->update_history(vm);
vm->get_requirements(cpu,mem,disk);
@@ -727,6 +743,8 @@ void LifeCycleManager::monitor_suspend_action(int vid)
vm->set_etime(the_time);
+ vm->set_vm_info();
+
vm->set_reason(History::STOP_RESUME);
vmpool->update_history(vm);
@@ -799,6 +817,8 @@ void LifeCycleManager::failure_action(VirtualMachine * vm)
vm->set_etime(the_time);
+ vm->set_vm_info();
+
vm->set_reason(History::ERROR);
vmpool->update_history(vm);
diff --git a/src/oca/java/src/org/opennebula/client/template/Template.java b/src/oca/java/src/org/opennebula/client/template/Template.java
index dff2fc1a2c..dd48c96254 100644
--- a/src/oca/java/src/org/opennebula/client/template/Template.java
+++ b/src/oca/java/src/org/opennebula/client/template/Template.java
@@ -35,6 +35,7 @@ public class Template extends PoolElement
private static final String CHOWN = METHOD_PREFIX + "chown";
private static final String CHMOD = METHOD_PREFIX + "chmod";
private static final String INSTANTIATE = METHOD_PREFIX + "instantiate";
+ private static final String CLONE = METHOD_PREFIX + "clone";
/**
* Creates a new Template representation.
@@ -205,6 +206,19 @@ public class Template extends PoolElement
return client.call(INSTANTIATE, id, name);
}
+ /**
+ * Clones this template into a new one
+ *
+ * @param client XML-RPC Client.
+ * @param id The template id of the target template.
+ * @param name Name for the new template.
+ * @return If successful the message contains the new template ID.
+ */
+ public static OneResponse clone(Client client, int id, String name)
+ {
+ return client.call(CLONE, id, name);
+ }
+
// =================================
// Instanced object XML-RPC methods
// =================================
@@ -375,6 +389,17 @@ public class Template extends PoolElement
return instantiate(client, id, "");
}
+ /**
+ * Clones this template into a new one
+ *
+ * @param name Name for the new template.
+ * @return If successful the message contains the new template ID.
+ */
+ public OneResponse clone(String name)
+ {
+ return clone(client, id, name);
+ }
+
// =================================
// Helpers
// =================================
diff --git a/src/onedb/3.4.0_to_3.4.1.rb b/src/onedb/3.4.0_to_3.4.1.rb
new file mode 100644
index 0000000000..b11206ad1d
--- /dev/null
+++ b/src/onedb/3.4.0_to_3.4.1.rb
@@ -0,0 +1,29 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); you may #
+# not use this file except in compliance with the License. You may obtain #
+# a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+#--------------------------------------------------------------------------- #
+
+module Migrator
+ def db_version
+ "3.4.1"
+ end
+
+ def one_version
+ "OpenNebula 3.4.1"
+ end
+
+ def up
+ return true
+ end
+end
diff --git a/src/onedb/3.4.1_to_3.5.80.rb b/src/onedb/3.4.1_to_3.5.80.rb
new file mode 100644
index 0000000000..42ebf9e3e6
--- /dev/null
+++ b/src/onedb/3.4.1_to_3.5.80.rb
@@ -0,0 +1,150 @@
+# -------------------------------------------------------------------------- #
+# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); you may #
+# not use this file except in compliance with the License. You may obtain #
+# a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+#--------------------------------------------------------------------------- #
+
+require "rexml/document"
+include REXML
+
+module Migrator
+ def db_version
+ "3.5.80"
+ end
+
+ def one_version
+ "OpenNebula 3.5.80"
+ end
+
+ def up
+
+ @db.run "ALTER TABLE datastore_pool RENAME TO old_datastore_pool;"
+ @db.run "CREATE TABLE datastore_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name));"
+
+ @db.fetch("SELECT * FROM old_datastore_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("DISK_TYPE").text = "0"
+
+ @db[:datastore_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_datastore_pool;"
+
+
+ @db.run "ALTER TABLE image_pool RENAME TO old_image_pool;"
+ @db.run "CREATE TABLE image_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, UNIQUE(name,uid) );"
+
+ @db.fetch("SELECT * FROM old_image_pool") do |row|
+ doc = Document.new(row[:body])
+
+ ds_id = ""
+ doc.root.each_element("DATASTORE_ID") { |e|
+ ds_id = e.text
+ }
+
+ doc.root.add_element("DISK_TYPE").text = "0"
+
+ @db[:image_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_image_pool;"
+
+
+ @db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
+ @db.run "CREATE TABLE vm_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, last_poll INTEGER, state INTEGER, lcm_state INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
+
+ @db.fetch("SELECT * FROM old_vm_pool") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("RESCHED").text = "0"
+
+ @db[:vm_pool].insert(
+ :oid => row[:oid],
+ :name => row[:name],
+ :body => doc.root.to_s,
+ :uid => row[:uid],
+ :gid => row[:gid],
+ :last_poll => row[:last_poll],
+ :state => row[:state],
+ :lcm_state => row[:lcm_state],
+ :owner_u => row[:owner_u],
+ :group_u => row[:group_u],
+ :other_u => row[:other_u])
+ end
+
+ @db.run "DROP TABLE old_vm_pool;"
+
+
+ @db.run "ALTER TABLE history RENAME TO old_history;"
+ @db.run "CREATE TABLE history (vid INTEGER, seq INTEGER, body TEXT, stime INTEGER, etime INTEGER, PRIMARY KEY(vid,seq));"
+
+ @db.fetch("SELECT * FROM old_history") do |row|
+ doc = Document.new(row[:body])
+
+ doc.root.add_element("OID").text = row[:vid].to_s
+
+ stime = "0"
+ doc.root.each_element("STIME") { |e|
+ stime = e.text
+ }
+
+ etime = "0"
+ doc.root.each_element("ETIME") { |e|
+ etime = e.text
+ }
+
+ @db.fetch("SELECT body FROM vm_pool WHERE oid = #{row[:vid]}") do |vm_row|
+ vm_doc = Document.new(vm_row[:body])
+
+ vm_doc.root.delete_element( '/VM/HISTORY_RECORDS/HISTORY' )
+
+ ["MEMORY", "CPU", "NET_TX", "NET_RX"].each { |elem_name|
+ vm_doc.root.each_element(elem_name) { |e|
+ e.text = "0"
+ }
+ }
+
+ doc.root.add_element( vm_doc )
+ end
+
+ @db[:history].insert(
+ :vid => row[:vid],
+ :seq => row[:seq],
+ :body => doc.root.to_s,
+ :stime => stime,
+ :etime => etime)
+ end
+
+ @db.run "DROP TABLE old_history;"
+
+
+ return true
+ end
+end
diff --git a/src/pool/PoolSQL.cc b/src/pool/PoolSQL.cc
index 06d47051d8..1afb6775cb 100644
--- a/src/pool/PoolSQL.cc
+++ b/src/pool/PoolSQL.cc
@@ -21,6 +21,7 @@
#include
#include "PoolSQL.h"
+#include "RequestManagerPoolInfoFilter.h"
#include
@@ -479,14 +480,8 @@ int PoolSQL::dump(ostringstream& oss,
const char * table,
const string& where)
{
- int rc;
ostringstream cmd;
- oss << "<" << elem_name << ">";
-
- set_callback(static_cast(&PoolSQL::dump_cb),
- static_cast(&oss));
-
cmd << "SELECT body FROM " << table;
if ( !where.empty() )
@@ -496,9 +491,26 @@ int PoolSQL::dump(ostringstream& oss,
cmd << " ORDER BY oid";
- rc = db->exec(cmd, this);
+ return dump(oss, elem_name, cmd);
+}
- oss << "" << elem_name << ">";
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+int PoolSQL::dump(ostringstream& oss,
+ const string& root_elem_name,
+ ostringstream& sql_query)
+{
+ int rc;
+
+ oss << "<" << root_elem_name << ">";
+
+ set_callback(static_cast(&PoolSQL::dump_cb),
+ static_cast(&oss));
+
+ rc = db->exec(sql_query, this);
+
+ oss << "" << root_elem_name << ">";
unset_callback();
@@ -546,3 +558,120 @@ int PoolSQL::search(
return rc;
}
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+void PoolSQL::acl_filter(int uid,
+ int gid,
+ PoolObjectSQL::ObjectType auth_object,
+ bool& all,
+ string& filter)
+{
+ filter.clear();
+
+ if ( uid == 0 || gid == 0 )
+ {
+ all = true;
+ return;
+ }
+
+ Nebula& nd = Nebula::instance();
+ AclManager* aclm = nd.get_aclm();
+
+ ostringstream acl_filter;
+ vector::iterator it;
+
+ vector oids;
+ vector gids;
+
+ aclm->reverse_search(uid,
+ gid,
+ auth_object,
+ AuthRequest::USE,
+ all,
+ oids,
+ gids);
+
+ for ( it = oids.begin(); it < oids.end(); it++ )
+ {
+ acl_filter << " OR oid = " << *it;
+ }
+
+ for ( it = gids.begin(); it < gids.end(); it++ )
+ {
+ acl_filter << " OR gid = " << *it;
+ }
+
+ filter = acl_filter.str();
+}
+
+/* -------------------------------------------------------------------------- */
+
+void PoolSQL::usr_filter(int uid,
+ int gid,
+ int filter_flag,
+ bool all,
+ const string& acl_str,
+ string& filter)
+{
+ ostringstream uid_filter;
+
+ if ( filter_flag == RequestManagerPoolInfoFilter::MINE )
+ {
+ uid_filter << "uid = " << uid;
+ }
+ else if ( filter_flag == RequestManagerPoolInfoFilter::MINE_GROUP )
+ {
+ uid_filter << " uid = " << uid
+ << " OR ( gid = " << gid << " AND group_u = 1 )";
+ }
+ else if ( filter_flag == RequestManagerPoolInfoFilter::ALL )
+ {
+ if (!all)
+ {
+ uid_filter << " uid = " << uid
+ << " OR ( gid = " << gid << " AND group_u = 1 )"
+ << " OR other_u = 1"
+ << acl_str;
+ }
+ }
+ else
+ {
+ uid_filter << "uid = " << filter_flag;
+
+ if ( filter_flag != uid && !all )
+ {
+ uid_filter << " AND ("
+ << " ( gid = " << gid << " AND group_u = 1)"
+ << " OR other_u = 1"
+ << acl_str
+ << ")";
+ }
+ }
+
+ filter = uid_filter.str();
+}
+
+/* -------------------------------------------------------------------------- */
+
+void PoolSQL::oid_filter(int start_id,
+ int end_id,
+ string& filter)
+{
+ ostringstream idfilter;
+
+ if ( start_id != -1 )
+ {
+ idfilter << "oid >= " << start_id;
+
+ if ( end_id != -1 )
+ {
+ idfilter << " AND oid <= " << end_id;
+ }
+ }
+
+ filter = idfilter.str();
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc
index f18bad3504..e2413c867c 100644
--- a/src/rm/RequestManager.cc
+++ b/src/rm/RequestManager.cc
@@ -243,6 +243,7 @@ void RequestManager::register_xml_methods()
xmlrpc_c::methodPtr vm_migrate(new VirtualMachineMigrate());
xmlrpc_c::methodPtr vm_action(new VirtualMachineAction());
xmlrpc_c::methodPtr vm_savedisk(new VirtualMachineSaveDisk());
+ xmlrpc_c::methodPtr vm_pool_acct(new VirtualMachinePoolAccounting());
// VirtualNetwork Methods
xmlrpc_c::methodPtr vn_addleases(new VirtualNetworkAddLeases());
@@ -348,6 +349,7 @@ void RequestManager::register_xml_methods()
RequestManagerRegistry.addMethod("one.vm.chmod", vm_chmod);
RequestManagerRegistry.addMethod("one.vmpool.info", vm_pool_info);
+ RequestManagerRegistry.addMethod("one.vmpool.accounting", vm_pool_acct);
/* VM Template related methods*/
RequestManagerRegistry.addMethod("one.template.update", template_update);
diff --git a/src/rm/RequestManagerPoolInfoFilter.cc b/src/rm/RequestManagerPoolInfoFilter.cc
index e40db5da8d..e48e23d237 100644
--- a/src/rm/RequestManagerPoolInfoFilter.cc
+++ b/src/rm/RequestManagerPoolInfoFilter.cc
@@ -91,6 +91,46 @@ void VirtualMachinePoolInfo::request_execute(
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
+void VirtualMachinePoolAccounting::request_execute(
+ xmlrpc_c::paramList const& paramList,
+ RequestAttributes& att)
+{
+ int filter_flag = xmlrpc_c::value_int(paramList.getInt(1));
+ int time_start = xmlrpc_c::value_int(paramList.getInt(2));
+ int time_end = xmlrpc_c::value_int(paramList.getInt(3));
+
+ ostringstream oss;
+ string where;
+ int rc;
+
+ if ( filter_flag < MINE )
+ {
+ failure_response(XML_RPC_API,
+ request_error("Incorrect filter_flag",""),
+ att);
+ return;
+ }
+
+ where_filter(att, filter_flag, -1, -1, "", "", where);
+
+ rc = (static_cast(pool))->dump_acct(oss,
+ where,
+ time_start,
+ time_end);
+ if ( rc != 0 )
+ {
+ failure_response(INTERNAL,request_error("Internal Error",""), att);
+ return;
+ }
+
+ success_response(oss.str(), att);
+
+ return;
+}
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+
void HostPoolInfo::request_execute(
xmlrpc_c::paramList const& paramList,
RequestAttributes& att)
@@ -141,6 +181,79 @@ void ClusterPoolInfo::request_execute(
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
+void RequestManagerPoolInfoFilter::where_filter(
+ RequestAttributes& att,
+ int filter_flag,
+ int start_id,
+ int end_id,
+ const string& and_clause,
+ const string& or_clause,
+ string& filter_str)
+{
+ bool empty = true;
+ bool all;
+
+ string acl_str;
+ string uid_str;
+ string oid_str;
+
+ ostringstream filter;
+
+ PoolSQL::acl_filter(att.uid, att.gid, auth_object, all, acl_str);
+
+ PoolSQL::usr_filter(att.uid, att.gid, filter_flag, all, acl_str, uid_str);
+
+ PoolSQL::oid_filter(start_id, end_id, oid_str);
+
+ // -------------------------------------------------------------------------
+ // Compound WHERE clause
+ // WHERE ( id_str ) AND ( uid_str ) AND ( and_clause ) OR ( or_clause )
+ // -------------------------------------------------------------------------
+
+ if (!oid_str.empty())
+ {
+ filter << "(" << oid_str << ")" ;
+ empty = false;
+ }
+
+ if (!uid_str.empty())
+ {
+ if (!empty)
+ {
+ filter << " AND ";
+ }
+
+ filter << "(" << uid_str << ")";
+ empty = false;
+ }
+
+ if (!and_clause.empty())
+ {
+ if (!empty)
+ {
+ filter << " AND ";
+ }
+
+ filter << "(" << and_clause << ")";
+ empty = false;
+ }
+
+ if (!or_clause.empty())
+ {
+ if (!empty)
+ {
+ filter << " OR ";
+ }
+
+ filter << "(" << or_clause << ")";
+ }
+
+ filter_str = filter.str();
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
void RequestManagerPoolInfoFilter::dump(
RequestAttributes& att,
int filter_flag,
@@ -149,20 +262,9 @@ void RequestManagerPoolInfoFilter::dump(
const string& and_clause,
const string& or_clause)
{
- set::iterator it;
-
ostringstream oss;
- bool empty = true;
- ostringstream where_string;
-
- ostringstream uid_filter;
- ostringstream id_filter;
-
- string uid_str;
- string acl_str;
- string id_str;
-
- int rc;
+ string where_string;
+ int rc;
if ( filter_flag < MINE )
{
@@ -172,148 +274,15 @@ void RequestManagerPoolInfoFilter::dump(
return;
}
- Nebula& nd = Nebula::instance();
- AclManager* aclm = nd.get_aclm();
- bool all;
- vector oids;
- vector gids;
+ where_filter(att,
+ filter_flag,
+ start_id,
+ end_id,
+ and_clause,
+ or_clause,
+ where_string);
- // -------------------------------------------------------------------------
- // User ID filter
- // -------------------------------------------------------------------------
-
- if ( att.uid == 0 || att.gid == 0 )
- {
- all = true;
- }
- else
- {
- ostringstream acl_filter;
- vector::iterator it;
-
- aclm->reverse_search(att.uid,
- att.gid,
- auth_object,
- AuthRequest::USE,
- all,
- oids,
- gids);
-
- for ( it = oids.begin(); it < oids.end(); it++ )
- {
- acl_filter << " OR oid = " << *it;
- }
-
- for ( it = gids.begin(); it < gids.end(); it++ )
- {
- acl_filter << " OR gid = " << *it;
- }
-
- acl_str = acl_filter.str();
- }
-
- switch ( filter_flag )
- {
- case MINE:
- uid_filter << "uid = " << att.uid;
- break;
-
- case MINE_GROUP:
- uid_filter << " uid = " << att.uid
- << " OR ( gid = " << att.gid << " AND group_u = 1 )";
- break;
-
- case ALL:
- if (!all)
- {
- uid_filter << " uid = " << att.uid
- << " OR ( gid = " << att.gid << " AND group_u = 1 )"
- << " OR other_u = 1"
- << acl_str;
- }
- break;
-
- default:
- uid_filter << "uid = " << filter_flag;
-
- if ( filter_flag != att.uid && !all )
- {
- uid_filter << " AND ("
- << " ( gid = " << att.gid << " AND group_u = 1)"
- << " OR other_u = 1"
- << acl_str
- << ")";
- }
- break;
- }
-
- uid_str = uid_filter.str();
-
- // ------------------------------------------
- // Resource ID filter
- // ------------------------------------------
-
- if ( start_id != -1 )
- {
- id_filter << "oid >= " << start_id;
-
- if ( end_id != -1 )
- {
- id_filter << " AND oid <= " << end_id;
- }
- }
-
- id_str = id_filter.str();
-
- // ------------------------------------------
- // Compound WHERE clause
- // ------------------------------------------
-
- // WHERE ( id_str ) AND ( uid_str ) AND ( and_clause ) OR ( or_clause )
-
- if (!id_str.empty())
- {
- where_string << "(" << id_str << ")" ;
- empty = false;
- }
-
- if (!uid_str.empty())
- {
- if (!empty)
- {
- where_string << " AND ";
- }
-
- where_string << "(" << uid_str << ")";
- empty = false;
- }
-
- if (!and_clause.empty())
- {
- if (!empty)
- {
- where_string << " AND ";
- }
-
- where_string << "(" << and_clause << ")";
- empty = false;
- }
-
- if (!or_clause.empty())
- {
- if (!empty)
- {
- where_string << " OR ";
- }
-
- where_string << "(" << or_clause << ")";
- }
-
- // ------------------------------------------
- // Get the pool
- // ------------------------------------------
-
- rc = pool->dump(oss,where_string.str());
+ rc = pool->dump(oss, where_string);
if ( rc != 0 )
{
@@ -325,4 +294,3 @@ void RequestManagerPoolInfoFilter::dump(
return;
}
-
diff --git a/src/sunstone/bin/sunstone-server b/src/sunstone/bin/sunstone-server
index e9b3b0e1ad..e4a4847ad4 100755
--- a/src/sunstone/bin/sunstone-server
+++ b/src/sunstone/bin/sunstone-server
@@ -35,6 +35,12 @@ fi
setup()
{
+ TMPDIR=$(grep ^:tmpdir: $SUNSTONE_CONF|awk '{print $2}')
+
+ if [ -n "$TMPDIR" ]; then
+ export TMPDIR
+ mkdir -p $TMPDIR
+ fi
if [ -f $SUNSTONE_LOCK_FILE ]; then
if [ -f $SUNSTONE_PID ]; then
diff --git a/src/sunstone/etc/sunstone-server.conf b/src/sunstone/etc/sunstone-server.conf
index 64915b50c0..54b4becb33 100644
--- a/src/sunstone/etc/sunstone-server.conf
+++ b/src/sunstone/etc/sunstone-server.conf
@@ -18,6 +18,9 @@
# Server Configuration
#############################################################
+# Directory to store temp files when uploading images
+:tmpdir: /var/tmp/one
+
# OpenNebula sever contact information
:one_xmlrpc: http://localhost:2633/RPC2
diff --git a/src/tm_mad/lvm/mvds b/src/tm_mad/lvm/mvds
index 0bf61fe5ae..341d94130c 100755
--- a/src/tm_mad/lvm/mvds
+++ b/src/tm_mad/lvm/mvds
@@ -25,7 +25,7 @@
SRC=$1
DST=$2
VM_ID=$3
-DS_ID=$3
+DS_ID=$4
if [ -z "${ONE_LOCATION}" ]; then
TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
diff --git a/src/tm_mad/qcow2/ln b/src/tm_mad/qcow2/ln
deleted file mode 100755
index 2a9395d484..0000000000
--- a/src/tm_mad/qcow2/ln
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/bash
-
-# -------------------------------------------------------------------------- #
-# Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) #
-# #
-# Licensed under the Apache License, Version 2.0 (the "License"); you may #
-# not use this file except in compliance with the License. You may obtain #
-# a copy of the License at #
-# #
-# http://www.apache.org/licenses/LICENSE-2.0 #
-# #
-# Unless required by applicable law or agreed to in writing, software #
-# distributed under the License is distributed on an "AS IS" BASIS, #
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
-# See the License for the specific language governing permissions and #
-# limitations under the License. #
-#--------------------------------------------------------------------------- #
-
-# ln fe:SOURCE host:remote_system_ds/disk.i
-# - fe is the front-end hostname
-# - SOURCE is the path of the disk image in the form DS_BASE_PATH/disk
-# - host is the target host to deploy the VM
-# - remote_system_ds is the path for the system datastore in the host
-
-SRC=$1
-DST=$2
-
-if [ -z "${ONE_LOCATION}" ]; then
- TMCOMMON=/var/lib/one/remotes/tm/tm_common.sh
-else
- TMCOMMON=$ONE_LOCATION/var/remotes/tm/tm_common.sh
-fi
-
-. $TMCOMMON
-
-#-------------------------------------------------------------------------------
-# Set dst path and dir
-#-------------------------------------------------------------------------------
-SRC_PATH=`arg_path $SRC`
-SRC_PATH="../../${SRC_PATH##"$DS_DIR/"}"
-
-DST_PATH=`arg_path $DST`
-DST_HOST=`arg_host $DST`
-DST_DIR=`dirname $DST_PATH`
-
-#-------------------------------------------------------------------------------
-# Link (ln) SRC into DST
-#-------------------------------------------------------------------------------
-
-# Is it a file or a folder (VMware)?
-if [ -d `arg_path $SRC` ]; then
- ssh_make_path $DST_HOST $DST_PATH
-
- # It's a folder, make links for all elements
- SRC_FOLDER_NAME=`basename $SRC_PATH`
- SRC_WITH_NO_FOLDER=`dirname $SRC_PATH`
- SRC_DS_NAME=`basename $SRC_WITH_NO_FOLDER`
- REL_SRC_PATH="../../../$SRC_DS_NAME/$SRC_FOLDER_NAME"
-
- log "Link all files in $SRC_PATH to $DST_PATH"
-
-LINK_SCRIPT=$(cat <"){};
/* -------------------------------------------------------------------------- */
@@ -61,7 +63,8 @@ History::History(
int _hid,
const string& _hostname,
const string& _vmm,
- const string& _vnm):
+ const string& _vnm,
+ const string& _vm_info):
oid(_oid),
seq(_seq),
hostname(_hostname),
@@ -76,7 +79,8 @@ History::History(
running_etime(0),
epilog_stime(0),
epilog_etime(0),
- reason(NONE)
+ reason(NONE),
+ vm_info(_vm_info)
{
non_persistent_data();
};
@@ -149,7 +153,7 @@ int History::insert_replace(SqlDB *db, bool replace)
return 0;
}
- sql_xml = db->escape_str(to_xml(xml_body).c_str());
+ sql_xml = db->escape_str(to_db_xml(xml_body).c_str());
if ( sql_xml == 0 )
{
@@ -168,7 +172,9 @@ int History::insert_replace(SqlDB *db, bool replace)
oss << " INTO " << table << " ("<< db_names <<") VALUES ("
<< oid << ","
<< seq << ","
- << "'" << sql_xml << "')";
+ << "'" << sql_xml << "',"
+ << stime << ","
+ << etime << ")";
rc = db->exec(oss);
@@ -259,11 +265,26 @@ ostream& operator<<(ostream& os, const History& history)
/* -------------------------------------------------------------------------- */
string& History::to_xml(string& xml) const
+{
+ return to_xml(xml, false);
+}
+
+/* -------------------------------------------------------------------------- */
+
+string& History::to_db_xml(string& xml) const
+{
+ return to_xml(xml, true);
+}
+
+/* -------------------------------------------------------------------------- */
+
+string& History::to_xml(string& xml, bool database) const
{
ostringstream oss;
oss <<
"" <<
+ "" << oid << "" <<
"" << seq << "" <<
"" << hostname << ""<<
"" << hid << "" <<
@@ -277,7 +298,14 @@ string& History::to_xml(string& xml) const
"" << running_etime << ""<<
"" << epilog_stime << ""<<
"" << epilog_etime << ""<<
- "" << reason << ""<<
+ "" << reason << "";
+
+ if ( database )
+ {
+ oss << vm_info;
+ }
+
+ oss <<
"";
xml = oss.str();
diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc
index e078231ee4..f3db0feb78 100644
--- a/src/vm/VirtualMachine.cc
+++ b/src/vm/VirtualMachine.cc
@@ -735,6 +735,7 @@ void VirtualMachine::add_history(
{
ostringstream os;
int seq;
+ string vm_xml;
if (history == 0)
{
@@ -747,12 +748,15 @@ void VirtualMachine::add_history(
previous_history = history;
}
+ to_xml_extended(vm_xml, 0);
+
history = new History(oid,
seq,
hid,
hostname,
vmm_mad,
- vnm_mad);
+ vnm_mad,
+ vm_xml);
history_records.push_back(history);
};
@@ -763,18 +767,22 @@ void VirtualMachine::add_history(
void VirtualMachine::cp_history()
{
History * htmp;
+ string vm_xml;
if (history == 0)
{
return;
}
+ to_xml_extended(vm_xml, 0);
+
htmp = new History(oid,
history->seq + 1,
history->hid,
history->hostname,
history->vmm_mad_name,
- history->vnm_mad_name);
+ history->vnm_mad_name,
+ vm_xml);
previous_history = history;
history = htmp;
@@ -788,18 +796,22 @@ void VirtualMachine::cp_history()
void VirtualMachine::cp_previous_history()
{
History * htmp;
+ string vm_xml;
if ( previous_history == 0 || history == 0)
{
return;
}
+ to_xml_extended(vm_xml, 0);
+
htmp = new History(oid,
history->seq + 1,
previous_history->hid,
previous_history->hostname,
previous_history->vmm_mad_name,
- previous_history->vnm_mad_name);
+ previous_history->vnm_mad_name,
+ vm_xml);
previous_history = history;
history = htmp;
@@ -1470,26 +1482,11 @@ error_yy:
pthread_mutex_unlock(&lex_mutex);
return -1;
}
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-string& VirtualMachine::to_xml(string& xml) const
-{
- return to_xml_extended(xml,false);
-}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-string& VirtualMachine::to_xml_extended(string& xml) const
-{
- return to_xml_extended(xml,true);
-}
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-string& VirtualMachine::to_xml_extended(string& xml, bool extended) const
+string& VirtualMachine::to_xml_extended(string& xml, int n_history) const
{
string template_xml;
string history_xml;
@@ -1517,11 +1514,11 @@ string& VirtualMachine::to_xml_extended(string& xml, bool extended) const
<< "" << net_rx << ""
<< obj_template->to_xml(template_xml);
- if ( hasHistory() )
+ if ( hasHistory() && n_history > 0 )
{
oss << "";
- if ( extended )
+ if ( n_history == 2 )
{
for (unsigned int i=0; i < history_records.size(); i++)
{
diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc
index f4e8fd6d02..7f7fa7d207 100644
--- a/src/vm/VirtualMachinePool.cc
+++ b/src/vm/VirtualMachinePool.cc
@@ -266,3 +266,37 @@ int VirtualMachinePool::get_pending(
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
+
+int VirtualMachinePool::dump_acct(ostringstream& oss,
+ const string& where,
+ int time_start,
+ int time_end)
+{
+ ostringstream cmd;
+
+ cmd << "SELECT " << History::table << ".body FROM " << History::table
+ << " INNER JOIN " << VirtualMachine::table
+ << " WHERE vid=oid";
+
+ if ( !where.empty() )
+ {
+ cmd << " AND " << where;
+ }
+
+ if ( time_start != -1 || time_end != -1 )
+ {
+ if ( time_start != -1 )
+ {
+ cmd << " AND (etime > " << time_start << " OR etime = 0)";
+ }
+
+ if ( time_end != -1 )
+ {
+ cmd << " AND stime < " << time_end;
+ }
+ }
+
+ cmd << " GROUP BY vid,seq";
+
+ return PoolSQL::dump(oss, "HISTORY_RECORDS", cmd);
+};
diff --git a/src/vmm/VirtualMachineManagerDriver.cc b/src/vmm/VirtualMachineManagerDriver.cc
index eb285860f7..06d636e697 100644
--- a/src/vmm/VirtualMachineManagerDriver.cc
+++ b/src/vmm/VirtualMachineManagerDriver.cc
@@ -546,8 +546,10 @@ void VirtualMachineManagerDriver::protocol(
}
vm->update_info(memory,cpu,net_tx,net_rx);
+ vm->set_vm_info();
vmpool->update(vm);
+ vmpool->update_history(vm);
if (state != '-' &&
(vm->get_lcm_state() == VirtualMachine::RUNNING ||
diff --git a/src/vmm_mad/ec2/one_vmm_ec2.rb b/src/vmm_mad/ec2/one_vmm_ec2.rb
index 05afb2aeb4..467b9e86f8 100755
--- a/src/vmm_mad/ec2/one_vmm_ec2.rb
+++ b/src/vmm_mad/ec2/one_vmm_ec2.rb
@@ -193,7 +193,7 @@ class EC2Driver < VirtualMachineDriver
return
end
- deploy_exe = exec_and_log_ec2(:run, ec2_info, id)
+ deploy_exe = exec_and_log_ec2(:run, ec2_info, "", id)
if deploy_exe.code != 0
msg = deploy_exe.stderr
send_message(ACTION[:deploy], RESULT[:failure], id, msg)
@@ -360,7 +360,7 @@ private
# +action+: Symbol, one of the keys of the EC2 hash constant (i.e :run)
# +xml+: REXML Document, containing EC2 information
# +extra_params+: String, extra information to be added to the command
- def exec_and_log_ec2(action, xml, extra_params="", id)
+ def exec_and_log_ec2(action, xml, extra_params, id)
cmd = EC2[action][:cmd].clone
cmd << ' ' << extra_params << ' ' if extra_params