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

Merge branch 'feature-1483'

This commit is contained in:
Ruben S. Montero 2013-02-08 22:13:57 +01:00
commit 3f0e3e8470
21 changed files with 822 additions and 117 deletions

View File

@ -351,6 +351,16 @@ protected:
*/
bool check(string& rs_attr, const vector<string> &restricted_attributes);
/**
* Updates the xml root element name
*
* @param _xml_root New name
*/
void set_xml_root(const char * _xml_root)
{
xml_root = _xml_root;
};
private:
bool replace_mode;

33
include/Util.h Normal file
View File

@ -0,0 +1,33 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
#ifndef UTIL_H_
#define UTIL_H_
#include <string>
namespace one_util
{
std::string& toupper(std::string& st);
std::string& tolower(std::string& st);
std::string log_time(time_t the_time);
std::string log_time();
};
#endif /* UTIL_H_ */

View File

@ -1178,7 +1178,7 @@ private:
int parse_context(string& error_str);
/**
* Parse the "REQUIREMENTS" attribute of the template by substituting
* Parse the "SCHED_REQUIREMENTS" attribute of the template by substituting
* $VARIABLE, $VARIABLE[ATTR] and $VARIABLE[ATTR, ATTR = VALUE]
* @param error_str Returns the error reason, if any
* @return 0 on success

View File

@ -45,7 +45,12 @@ public:
{
return Template::check(rs_attr, restricted_attributes);
};
void set_xml_root(const char * _xml_root)
{
Template::set_xml_root(_xml_root);
};
private:
friend class VirtualMachinePool;

View File

@ -499,6 +499,10 @@ DEFAULT_UMASK = 177
VM_RESTRICTED_ATTR = "CONTEXT/FILES"
VM_RESTRICTED_ATTR = "NIC/MAC"
VM_RESTRICTED_ATTR = "NIC/VLAN_ID"
VM_RESTRICTED_ATTR = "RANK"
#VM_RESTRICTED_ATTR = "RANK"
#VM_RESTRICTED_ATTR = "SCHED_RANK"
#VM_RESTRICTED_ATTR = "REQUIREMENTS"
#VM_RESTRICTED_ATTR = "SCHED_REQUIREMENTS"
IMAGE_RESTRICTED_ATTR = "SOURCE"

View File

@ -252,6 +252,9 @@ module CLIHelper
if @columns[field]
minus=( @columns[field][:left] ? "-" : "" )
size=@columns[field][:size]
if @columns[field][:donottruncate]
return "%#{minus}#{size}s" % [ data.to_s ]
end
return "%#{minus}#{size}.#{size}s" % [ data.to_s ]
else
exit -1, "Column #{field} not defined."

View File

@ -577,13 +577,19 @@ EOT
end
end
def OpenNebulaHelper.time_to_str(time)
def OpenNebulaHelper.time_to_str(time, print_seconds=true)
value=time.to_i
if value==0
value='-'
else
value=Time.at(value).strftime("%m/%d %H:%M:%S")
if print_seconds
value=Time.at(value).strftime("%m/%d %H:%M:%S")
else
value=Time.at(value).strftime("%m/%d %H:%M")
end
end
return value
end
def OpenNebulaHelper.period_to_str(time, print_seconds=true)

View File

@ -15,6 +15,7 @@
#--------------------------------------------------------------------------- #
require 'one_helper'
require 'optparse/time'
class OneVMHelper < OpenNebulaHelper::OneHelper
MULTIPLE={
@ -57,6 +58,13 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
:description => "Creates the new VM on hold state instead of pending"
}
SCHEDULE = {
:name => "schedule",
:large => "--schedule TIME",
:description => "Schedules this action to be executed after the given time",
:format => Time
}
def self.rname
"VM"
end
@ -141,6 +149,38 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
table
end
def schedule_actions(ids,options,action)
# Verbose by default
options[:verbose] = true
perform_actions(
ids, options,
"#{action} scheduled at #{options[:schedule]}") do |vm|
rc = vm.info
if OpenNebula.is_error?(rc)
puts rc.message
exit -1
end
ids = vm.retrieve_elements('USER_TEMPLATE/SCHED_ACTION/ID')
id = 0
if (!ids.nil? && !ids.empty?)
ids.map! {|e| e.to_i }
id = ids.max + 1
end
tmp_str = vm.user_template_str
tmp_str << "\nSCHED_ACTION = [ID = #{id}, ACTION = #{action}, TIME = #{options[:schedule].to_i}]"
vm.update(tmp_str)
end
end
private
def factory(id=nil)
@ -212,12 +252,43 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
}
puts
if vm.has_elements?("/VM/USER_TEMPLATE/SCHED_ACTION")
CLIHelper.print_header(str_h1 % "SCHEDULED ACTIONS",false)
CLIHelper::ShowTable.new(nil, self) do
column :"ID", "", :size=>2 do |d|
d["ID"] if !d.nil?
end
column :"ACTION", "", :left, :size=>10 do |d|
d["ACTION"] if !d.nil?
end
column :"SCHEDULED", "", :size=>12 do |d|
OpenNebulaHelper.time_to_str(d["TIME"], false) if !d.nil?
end
column :"DONE", "", :size=>12 do |d|
OpenNebulaHelper.time_to_str(d["DONE"], false) if !d.nil?
end
column :"MESSAGE", "", :left, :donottruncate, :size=>40 do |d|
d["MESSAGE"] if !d.nil?
end
end.show([vm.to_hash['VM']['USER_TEMPLATE']['SCHED_ACTION']].flatten, {})
puts
end
CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE TEMPLATE",false)
puts vm.template_str
if vm.has_elements?("/VM/USER_TEMPLATE")
puts
vm.delete_element("/VM/USER_TEMPLATE/SCHED_ACTION")
CLIHelper.print_header(str_h1 % "USER TEMPLATE",false)
puts vm.template_like_str('USER_TEMPLATE')
end

View File

@ -192,9 +192,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: ANY
EOT
command :delete, delete_desc, [:range, :vmid_list] do
helper.perform_actions(args[0],options,"deleted") do |vm|
vm.finalize
command :delete, delete_desc, [:range, :vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"deleted") do |vm|
vm.finalize
end
end
end
@ -205,9 +210,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: PENDING
EOT
command :hold, hold_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"put on hold") do |vm|
vm.hold
command :hold, hold_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"put on hold") do |vm|
vm.hold
end
end
end
@ -217,9 +227,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: HOLD
EOT
command :release, release_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"released") do |vm|
vm.release
command :release, release_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"released") do |vm|
vm.release
end
end
end
@ -257,9 +272,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :shutdown, shutdown_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"shutting down") do |vm|
vm.shutdown
command :shutdown, shutdown_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"shutting down") do |vm|
vm.shutdown
end
end
end
@ -270,9 +290,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :poweroff, poweroff_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"shutting down") do |vm|
vm.poweroff
command :poweroff, poweroff_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"shutting down") do |vm|
vm.poweroff
end
end
end
@ -283,9 +308,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :reboot, reboot_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"rebooting") do |vm|
vm.reboot
command :reboot, reboot_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"rebooting") do |vm|
vm.reboot
end
end
end
@ -295,9 +325,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :reset, reset_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"resetting") do |vm|
vm.reset
command :reset, reset_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"resetting") do |vm|
vm.reset
end
end
end
@ -366,9 +401,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: UNKNOWN, BOOT, POWEROFF
EOT
command :restart, restart_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"restarting") do |vm|
vm.restart
command :restart, restart_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"restarting") do |vm|
vm.restart
end
end
end
@ -380,9 +420,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: ANY, except SUSPENDED or DONE
EOT
command :resubmit, resubmit_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"resubmiting") do |vm|
vm.resubmit
command :resubmit, resubmit_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"resubmiting") do |vm|
vm.resubmit
end
end
end
@ -394,9 +439,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :cancel, cancel_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"canceling") do |vm|
vm.cancel
command :cancel, cancel_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"canceling") do |vm|
vm.cancel
end
end
end
@ -407,9 +457,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :stop, stop_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"stopping") do |vm|
vm.stop
command :stop, stop_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"stopping") do |vm|
vm.stop
end
end
end
@ -422,9 +477,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: RUNNING
EOT
command :suspend, suspend_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"suspending") do |vm|
vm.suspend
command :suspend, suspend_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"suspending") do |vm|
vm.suspend
end
end
end
@ -434,9 +494,14 @@ cmd=CommandParser::CmdParser.new(ARGV) do
States: STOPPED, SUSPENDED
EOT
command :resume, resume_desc, [:range,:vmid_list] do
helper.perform_actions(args[0],options,"resuming") do |vm|
vm.resume
command :resume, resume_desc, [:range,:vmid_list],
:options => [OneVMHelper::SCHEDULE] do
if (!options[:schedule].nil?)
helper.schedule_actions(args[0], options, @comm_name)
else
helper.perform_actions(args[0],options,"resuming") do |vm|
vm.resume
end
end
end

View File

@ -25,7 +25,8 @@ source_files=[
'ActionManager.cc',
'Attribute.cc',
'mem_collector.c',
'SSLTools.cc'
'SSLTools.cc',
'Util.cc'
]
# Build library

53
src/common/Util.cc Normal file
View File

@ -0,0 +1,53 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2013, OpenNebula Project (OpenNebula.org), C12G Labs */
/* */
/* 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. */
/* -------------------------------------------------------------------------- */
#include "Util.h"
#include <algorithm>
using namespace std;
string& one_util::toupper(string& st)
{
transform(st.begin(),st.end(),st.begin(),(int(*)(int))toupper);
return st;
};
string& one_util::tolower(string& st)
{
transform(st.begin(),st.end(),st.begin(),(int(*)(int))tolower);
return st;
};
string one_util::log_time(time_t the_time)
{
char time_str[26];
#ifdef SOLARIS
ctime_r(&(the_time),time_str,sizeof(char)*26);
#else
ctime_r(&(the_time),time_str);
#endif
time_str[24] = '\0'; // Get rid of final enter character
return string(time_str);
};
string one_util::log_time()
{
return log_time( time(0) );
};

View File

@ -25,7 +25,7 @@ lib_name='nebula_core'
source_files=[
'SystemDB.cc',
'Nebula.cc',
'NebulaTemplate.cc',
'NebulaTemplate.cc'
]
# Build library

View File

@ -155,6 +155,26 @@ module OpenNebula
super(VM_METHODS[:update], new_template)
end
# Returns the <USER_TEMPLATE> element in text form
#
# @param indent [true,false] indents the resulting string, defaults to true
#
# @return [String] The USER_TEMPLATE
def user_template_str(indent=true)
template_like_str('USER_TEMPLATE', indent)
end
# Returns the <USER_TEMPLATE> element in XML form
#
# @return [String] The USER_TEMPLATE
def user_template_xml
if NOKOGIRI
@xml.xpath('TEMPLATE').to_s
else
@xml.elements['TEMPLATE'].to_s
end
end
# Initiates the instance of the VM on the target host.
#

View File

@ -402,6 +402,10 @@ module Migrator
########################################################################
# Feature #1556: New elem USER_TEMPLATE
#
# Feature #1483: Move scheduling attributes
# /VM/TEMPLATE/REQUIREMENTS -> USER_TEMPLATE/SCHED_REQUIREMENTS
# /VM/TEMPLATE/RANK -> USER_TEMPLATE/SCHED_RANK
########################################################################
@db.run "ALTER TABLE vm_pool RENAME TO old_vm_pool;"
@ -410,7 +414,21 @@ module Migrator
@db.fetch("SELECT * FROM old_vm_pool") do |row|
doc = Document.new(row[:body])
doc.root.add_element("USER_TEMPLATE")
user_template = doc.root.add_element("USER_TEMPLATE")
doc.root.each_element("TEMPLATE") do |e|
elem = e.delete_element("REQUIREMENTS")
if !elem.nil?
user_template.add_element("SCHED_REQUIREMENTS").text = elem.text
end
elem = e.delete_element("RANK")
if !elem.nil?
user_template.add_element("SCHED_RANK").text = elem.text
end
end
@db[:vm_pool].insert(
:oid => row[:oid],
@ -429,6 +447,53 @@ module Migrator
@db.run "DROP TABLE old_vm_pool;"
########################################################################
# Feature #1483: Move scheduling attributes
# /VMTEMPLATE/TEMPLATE/REQUIREMENTS -> /VMTEMPLATE/TEMPLATE/SCHED_REQUIREMENTS
# /VMTEMPLATE/TEMPLATE/RANK -> /VMTEMPLATE/TEMPLATE/SCHED_RANK
########################################################################
@db.run "ALTER TABLE template_pool RENAME TO old_template_pool;"
@db.run "CREATE TABLE template_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body TEXT, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER);"
@db.fetch("SELECT * FROM old_template_pool") do |row|
doc = Document.new(row[:body])
template = nil
doc.root.each_element("TEMPLATE") do |e|
template = e
end
doc.root.each_element("TEMPLATE") do |e|
elem = e.delete_element("REQUIREMENTS")
if !elem.nil?
template.add_element("SCHED_REQUIREMENTS").text = elem.text
end
elem = e.delete_element("RANK")
if !elem.nil?
template.add_element("SCHED_RANK").text = elem.text
end
end
@db[:template_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_template_pool;"
########################################################################
#
# Banner for the new /var/lib/one/vms directory

View File

@ -50,6 +50,7 @@ protected:
hpool(0),
clpool(0),
vmpool(0),
vmapool(0),
acls(0),
timer(0),
url(""),
@ -79,6 +80,11 @@ protected:
delete vmpool;
}
if ( vmapool != 0)
{
delete vmapool;
}
if ( acls != 0)
{
delete acls;
@ -94,11 +100,13 @@ protected:
// Pools
// ---------------------------------------------------------------
HostPoolXML * hpool;
ClusterPoolXML * clpool;
VirtualMachinePoolXML * vmpool;
HostPoolXML * hpool;
ClusterPoolXML * clpool;
AclXML * acls;
VirtualMachinePoolXML * vmpool;
VirtualMachineActionsPoolXML* vmapool;
AclXML * acls;
// ---------------------------------------------------------------
// Scheduler Policies
@ -133,6 +141,9 @@ protected:
*/
virtual int set_up_pools();
virtual int do_scheduled_actions();
private:
Scheduler(Scheduler const&){};

View File

@ -32,7 +32,7 @@ public:
bool _live_resched):
PoolXML(client, machines_limit), live_resched(_live_resched){};
~VirtualMachinePoolXML(){};
virtual ~VirtualMachinePoolXML(){};
/**
* Retrieves the pending and rescheduling VMs
@ -66,12 +66,16 @@ public:
* Update the VM template
* @param vid the VM id
* @param st the template string
*
* @return 0 on success, -1 otherwise
*/
int update(int vid, const string &st) const;
/**
* Update the VM template
* @param the VM
*
* @return 0 on success, -1 otherwise
*/
int update(VirtualMachineXML * vm) const
{
@ -86,14 +90,62 @@ protected:
{
return get_nodes("/VM_POOL/VM[STATE=1 or (LCM_STATE=3 and RESCHED=1)]",
content);
};
}
virtual void add_object(xmlNodePtr node);
virtual int load_info(xmlrpc_c::value &result);
/* Do live migrations to resched VMs*/
/**
* Do live migrations to resched VMs
*/
bool live_resched;
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
class VirtualMachineActionsPoolXML : public VirtualMachinePoolXML
{
public:
VirtualMachineActionsPoolXML(Client* client,
unsigned int machines_limit):
VirtualMachinePoolXML(client, machines_limit, false){};
virtual ~VirtualMachineActionsPoolXML(){};
/**
* Retrieves the VMs with pending actions
*
* @return 0 on success
* -1 on error
* -2 if no VMs with pending actions
*/
int set_up();
/**
* Calls one.vm.action
*
* @param vid The VM id
* @param action Action argument (shutdown, hold, release...)
* @param error_msg Error reason, if any
*
* @return 0 on success, -1 otherwise
*/
int action(int vid, const string &action, string &error_msg) const;
protected:
int get_suitable_nodes(vector<xmlNodePtr>& content)
{
ostringstream oss;
oss << "/VM_POOL/VM/USER_TEMPLATE/SCHED_ACTION[TIME < " << time(0)
<< " and not(DONE > 0)]/../..";
return get_nodes(oss.str().c_str(), content);
}
};
#endif /* VM_POOL_XML_H_ */

View File

@ -124,6 +124,37 @@ public:
return xml_str;
}
/**
* Removes (but does not delete) the scheduled actions of the VM
*
* @param attributes to hold the VM actions
*/
void get_actions(vector<Attribute *>& attributes) const
{
attributes.clear();
vm_template->remove("SCHED_ACTION", attributes);
}
/**
* Sets an attribute in the VM Template, it must be allocated in the heap
*
* @param attributes to hold the VM actions
*/
void set_attribute(Attribute* att)
{
return vm_template->set(att);
}
/**
* Checks the action to be performed and returns the corresponding XML-RPC
* method name.
* @param action_st, the action to be performed. The XML-RPC name is
* returned here
* @return 0 on success.
*/
static int parse_action_name(string& action_st);
/**
* Function to write a Virtual Machine in an output stream
*/

View File

@ -209,3 +209,76 @@ int VirtualMachinePoolXML::update(int vid, const string &st) const
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachineActionsPoolXML::set_up()
{
ostringstream oss;
int rc;
rc = PoolXML::set_up();
if ( rc == 0 )
{
if (objects.empty())
{
return -2;
}
oss.str("");
oss << "VMs with scheduled actions:" << endl;
map<int,ObjectXML*>::iterator it;
for (it=objects.begin();it!=objects.end();it++)
{
oss << " " << it->first;
}
NebulaLog::log("VM",Log::DEBUG,oss);
}
return rc;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachineActionsPoolXML::action(
int vid,
const string& action,
string& error_msg) const
{
xmlrpc_c::value result;
bool success;
try
{
client->call( client->get_endpoint(), // serverUrl
"one.vm.action", // methodName
"ssi", // arguments format
&result, // resultP
client->get_oneauth().c_str(), // session
action.c_str(), // action
vid // VM ID
);
}
catch (exception const& e)
{
return -1;
}
vector<xmlrpc_c::value> values =
xmlrpc_c::value_array(result).vectorValueValue();
success = xmlrpc_c::value_boolean(values[0]);
if (!success)
{
error_msg = xmlrpc_c::value_string( values[1] );
return -1;
}
return 0;
}

View File

@ -17,6 +17,7 @@
#include <algorithm>
#include "VirtualMachineXML.h"
#include "Util.h"
void VirtualMachineXML::init_attributes()
{
@ -51,7 +52,7 @@ void VirtualMachineXML::init_attributes()
cpu = 0;
}
result = ((*this)["/VM/TEMPLATE/RANK"]);
result = ((*this)["/VM/USER_TEMPLATE/SCHED_RANK"]);
if (result.size() > 0)
{
@ -59,18 +60,42 @@ void VirtualMachineXML::init_attributes()
}
else
{
rank = "";
// Compatibility with previous versions
result = ((*this)["/VM/USER_TEMPLATE/RANK"]);
if (result.size() > 0)
{
rank = result[0];
}
else
{
rank = "";
}
}
result = ((*this)["/VM/TEMPLATE/REQUIREMENTS"]);
result = ((*this)["/VM/TEMPLATE/AUTOMATIC_REQUIREMENTS"]);
if (result.size() > 0)
{
requirements = result[0];
}
else
result = ((*this)["/VM/USER_TEMPLATE/SCHED_REQUIREMENTS"]);
if (result.size() > 0)
{
requirements = "";
if ( !requirements.empty() )
{
ostringstream oss;
oss << requirements << " & ( " << result[0] << " )";
requirements = oss.str();
}
else
{
requirements = result[0];
}
}
result = ((*this)["/VM/HISTORY_RECORDS/HISTORY/HID"]);
@ -255,21 +280,42 @@ void VirtualMachineXML::log(const string &st)
{
return;
}
ostringstream oss;
char str[26];
time_t the_time = time(NULL);
ostringstream oss;
#ifdef SOLARIS
ctime_r(&(the_time),str,sizeof(char)*26);
#else
ctime_r(&(the_time),str);
#endif
str[24] = '\0'; // Get rid of final enter character
oss << str << " : " << st;
oss << one_util::log_time() << " : " << st;
vm_template->replace("SCHED_MESSAGE", oss.str());
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int VirtualMachineXML::parse_action_name(string& action_st)
{
one_util::tolower(action_st);
// onevm delete command uses the xml-rpc finalize action
if (action_st == "delete")
{
action_st = "finalize";
}
if ( action_st != "shutdown"
&& action_st != "hold"
&& action_st != "release"
&& action_st != "stop"
&& action_st != "cancel"
&& action_st != "suspend"
&& action_st != "resume"
&& action_st != "restart"
&& action_st != "resubmit"
&& action_st != "reboot"
&& action_st != "reset"
&& action_st != "poweroff"
&& action_st != "finalize")
{
return -1;
}
return 0;
};

View File

@ -34,6 +34,7 @@
#include "RankPolicy.h"
#include "NebulaLog.h"
#include "PoolObjectAuth.h"
#include "Util.h"
using namespace std;
@ -214,6 +215,8 @@ void Scheduler::start()
vmpool = new VirtualMachinePoolXML(client,
machines_limit,
(live_rescheds == 1));
vmapool= new VirtualMachineActionsPoolXML(client, machines_limit);
acls = new AclXML(client);
// -----------------------------------------------------------
@ -465,7 +468,7 @@ void Scheduler::match()
matched = false;
n_error++;
error_msg << "Error evaluating REQUIREMENTS expression: '"
error_msg << "Error evaluating SCHED_REQUIREMENTS expression: '"
<< reqs << "', error: " << error;
oss << "VM " << oid << ": " << error_msg.str();
@ -488,7 +491,7 @@ void Scheduler::match()
ostringstream oss;
oss << "VM " << oid << ": Host " << host->get_hid() <<
" filtered out. It does not fulfill REQUIREMENTS.";
" filtered out. It does not fulfill SCHED_REQUIREMENTS.";
NebulaLog::log("SCHED",Log::DEBUG,oss);
continue;
@ -537,7 +540,7 @@ void Scheduler::match()
}
else if (n_matched == 0)
{
vm->log("No host meets the REQUIREMENTS expression");
vm->log("No host meets the SCHED_REQUIREMENTS expression");
}
else
{
@ -658,12 +661,117 @@ void Scheduler::dispatch()
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
int Scheduler::do_scheduled_actions()
{
VirtualMachineXML* vm;
const map<int, ObjectXML*> vms = vmapool->get_objects();
map<int, ObjectXML*>::const_iterator vm_it;
vector<Attribute *> attributes;
vector<Attribute *>::iterator it;
VectorAttribute* vatt;
int action_time;
int done_time;
int has_time;
int has_done;
string action_st, error_msg;
time_t the_time = time(0);
string time_str = one_util::log_time(the_time);
for (vm_it=vms.begin(); vm_it != vms.end(); vm_it++)
{
vm = static_cast<VirtualMachineXML*>(vm_it->second);
vm->get_actions(attributes);
// TODO: Sort actions by TIME
for (it=attributes.begin(); it != attributes.end(); it++)
{
vatt = dynamic_cast<VectorAttribute*>(*it);
if (vatt == 0)
{
if ( *it != 0 )
{
delete *it;
}
continue;
}
has_time = vatt->vector_value("TIME", action_time);
has_done = vatt->vector_value("DONE", done_time);
action_st = vatt->vector_value("ACTION");
if (has_time == 0 && has_done == -1 && action_time < the_time)
{
ostringstream oss;
int rc = VirtualMachineXML::parse_action_name(action_st);
oss << "Executing action '" << action_st << "' for VM "
<< vm->get_oid() << " : ";
if ( rc != 0 )
{
error_msg = "This action is not supported.";
}
else
{
rc = vmapool->action(vm->get_oid(), action_st, error_msg);
}
if (rc == 0)
{
vatt->remove("MESSAGE");
vatt->replace("DONE", static_cast<int>(the_time));
oss << "Success.";
}
else
{
ostringstream oss_aux;
oss_aux << time_str << " : " << error_msg;
vatt->replace("MESSAGE", oss_aux.str());
oss << "Failure. " << error_msg;
}
NebulaLog::log("VM", Log::INFO, oss);
}
vm->set_attribute(vatt);
}
vmpool->update(vm);
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Scheduler::do_action(const string &name, void *args)
{
int rc;
if (name == ACTION_TIMER)
{
rc = vmapool->set_up();
if ( rc == 0 )
{
do_scheduled_actions();
}
rc = set_up_pools();
if ( rc != 0 )

View File

@ -63,14 +63,17 @@ VirtualMachine::VirtualMachine(int id,
{
if (_vm_template != 0)
{
obj_template = _vm_template;
// This is a VM Template, with the root TEMPLATE.
_vm_template->set_xml_root("USER_TEMPLATE");
user_obj_template = _vm_template;
}
else
{
obj_template = new VirtualMachineTemplate;
user_obj_template = new Template(false,'=',"USER_TEMPLATE");
}
user_obj_template = new Template(false,'=',"USER_TEMPLATE");
obj_template = new VirtualMachineTemplate;
set_umask(umask);
}
@ -257,13 +260,24 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
oss << oid;
value = oss.str();
replace_template_attribute("VMID", value);
user_obj_template->erase("VMID");
obj_template->add("VMID", value);
get_template_attribute("NAME",name);
user_obj_template->get("TEMPLATE_ID", value);
user_obj_template->erase("TEMPLATE_ID");
if (!value.empty())
{
obj_template->add("TEMPLATE_ID", value);
}
user_obj_template->get("NAME",name);
user_obj_template->erase("NAME");
if (name.empty() == true)
{
get_template_attribute("TEMPLATE_NAME", prefix);
user_obj_template->get("TEMPLATE_NAME", prefix);
user_obj_template->erase("TEMPLATE_NAME");
if (prefix.empty())
{
@ -273,8 +287,6 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
oss.str("");
oss << prefix << "-" << oid;
name = oss.str();
replace_template_attribute("NAME", name);
}
else if (name.length() > 128)
{
@ -287,26 +299,35 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
// Check for CPU, VCPU and MEMORY attributes
// ------------------------------------------------------------------------
if ( get_template_attribute("MEMORY", ivalue) == false || ivalue <= 0 )
if ( user_obj_template->get("MEMORY", ivalue) == false || ivalue <= 0 )
{
goto error_memory;
}
if ( get_template_attribute("CPU", fvalue) == false || fvalue <= 0 )
user_obj_template->erase("MEMORY");
obj_template->add("MEMORY", ivalue);
if ( user_obj_template->get("CPU", fvalue) == false || fvalue <= 0 )
{
goto error_cpu;
}
user_obj_template->erase("CPU");
obj_template->add("CPU", fvalue);
// VCPU is optional, first check if the attribute exists, then check it is
// an integer
get_template_attribute("VCPU", value);
user_obj_template->get("VCPU", value);
if ( value.empty() == false )
{
if ( get_template_attribute("VCPU", ivalue) == false || ivalue <= 0 )
if ( user_obj_template->get("VCPU", ivalue) == false || ivalue <= 0 )
{
goto error_vcpu;
}
user_obj_template->erase("VCPU");
obj_template->add("VCPU", ivalue);
}
// ------------------------------------------------------------------------
@ -532,7 +553,14 @@ int VirtualMachine::parse_os(string& error_str)
vector<Attribute *> os_attr;
VectorAttribute * os;
num = obj_template->get("OS", os_attr);
vector<Attribute *>::iterator it;
num = user_obj_template->remove("OS", os_attr);
for (it=os_attr.begin(); it != os_attr.end(); it++)
{
obj_template->set(*it);
}
if ( num == 0 )
{
@ -724,7 +752,14 @@ void VirtualMachine::parse_graphics()
vector<Attribute *> array_graphics;
VectorAttribute * graphics;
num = obj_template->get("GRAPHICS", array_graphics);
vector<Attribute *>::iterator it;
num = user_obj_template->remove("GRAPHICS", array_graphics);
for (it=array_graphics.begin(); it != array_graphics.end(); it++)
{
obj_template->set(*it);
}
if ( num == 0 )
{
@ -771,7 +806,16 @@ int VirtualMachine::parse_requirements(string& error_str)
string parsed;
num = obj_template->remove("REQUIREMENTS", array_reqs);
num = user_obj_template->remove("SCHED_REQUIREMENTS", array_reqs);
if ( num == 0 ) // Compatibility with old REQUIREMENTS attribute
{
num = user_obj_template->remove("REQUIREMENTS", array_reqs);
}
else
{
user_obj_template->erase("REQUIREMENTS");
}
if ( num == 0 )
{
@ -779,7 +823,7 @@ int VirtualMachine::parse_requirements(string& error_str)
}
else if ( num > 1 )
{
error_str = "Only one REQUIREMENTS attribute can be defined.";
error_str = "Only one SCHED_REQUIREMENTS attribute can be defined.";
goto error_cleanup;
}
@ -787,7 +831,7 @@ int VirtualMachine::parse_requirements(string& error_str)
if ( reqs == 0 )
{
error_str = "Wrong format for REQUIREMENTS attribute.";
error_str = "Wrong format for SCHED_REQUIREMENTS attribute.";
goto error_cleanup;
}
@ -797,19 +841,13 @@ int VirtualMachine::parse_requirements(string& error_str)
{
SingleAttribute * reqs_parsed;
reqs_parsed = new SingleAttribute("REQUIREMENTS",parsed);
obj_template->set(reqs_parsed);
reqs_parsed = new SingleAttribute("SCHED_REQUIREMENTS",parsed);
user_obj_template->set(reqs_parsed);
}
/* --- Delete old requirements attributes --- */
/* --- Delete old requirements attribute --- */
for (int i = 0; i < num ; i++)
{
if (array_reqs[i] != 0)
{
delete array_reqs[i];
}
}
delete array_reqs[0];
return rc;
@ -943,14 +981,7 @@ int VirtualMachine::automatic_requirements(string& error_str)
oss.str("");
oss << "CLUSTER_ID = " << cluster_id;
obj_template->get("REQUIREMENTS", requirements);
if ( !requirements.empty() )
{
oss << " & ( " << requirements << " )";
}
replace_template_attribute("REQUIREMENTS", oss.str());
obj_template->add("AUTOMATIC_REQUIREMENTS", oss.str());
}
return 0;
@ -1310,11 +1341,23 @@ int VirtualMachine::get_disk_images(string& error_str)
Nebula& nd = Nebula::instance();
ipool = nd.get_ipool();
vector<Attribute*>::iterator it;
// -------------------------------------------------------------------------
// The context is the first of the cdroms
// -------------------------------------------------------------------------
num_context = obj_template->get("CONTEXT", context_disks);
num_disks = obj_template->get("DISK", disks);
num_context = user_obj_template->remove("CONTEXT", context_disks);
num_disks = user_obj_template->remove("DISK", disks);
for (it=context_disks.begin(); it != context_disks.end(); it++)
{
obj_template->set(*it);
}
for (it=disks.begin(); it != disks.end(); it++)
{
obj_template->set(*it);
}
if ( num_disks > 20 )
{
@ -1429,11 +1472,11 @@ error_duplicated_target:
error_common:
ImageManager * imagem = nd.get_imagem();
vector<int>::iterator it;
vector<int>::iterator img_it;
for ( it=acquired_images.begin() ; it < acquired_images.end(); it++ )
for ( img_it=acquired_images.begin() ; img_it < acquired_images.end(); img_it++ )
{
imagem->release_image(oid, *it, false);
imagem->release_image(oid, *img_it, false);
}
return -1;
@ -1770,7 +1813,12 @@ int VirtualMachine::get_network_leases(string& estr)
Nebula& nd = Nebula::instance();
vnpool = nd.get_vnpool();
num_nics = obj_template->get("NIC",nics);
num_nics = user_obj_template->remove("NIC",nics);
for (vector<Attribute*>::iterator it=nics.begin(); it != nics.end(); it++)
{
obj_template->set(*it);
}
for(int i=0; i<num_nics; i++)
{