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}\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 << ""; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +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 << ""; 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