mirror of
https://github.com/OpenNebula/one.git
synced 2025-02-08 05:57:23 +03:00
Merge branch 'feature-3383'
This commit is contained in:
commit
3ecbdad163
@ -94,6 +94,15 @@ public:
|
||||
int deploy (
|
||||
VirtualMachine * vm);
|
||||
|
||||
/**
|
||||
* Sets an imported VM to RUNNING state, a history record MUST be added,
|
||||
* and the VM MUST be locked.
|
||||
* @param vm pointer to a VirtualMachine with its mutex locked.
|
||||
* @return 0 on success
|
||||
*/
|
||||
int import (
|
||||
VirtualMachine * vm);
|
||||
|
||||
/**
|
||||
* Migrates a VM. The following actions must be performed before calling
|
||||
* this function:
|
||||
|
@ -104,6 +104,15 @@ public:
|
||||
return static_cast<VirtualMachine *>(PoolSQL::get(oid,lock));
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a VM ID by its deploy_id, the dedploy_id - VM id mapping is keep
|
||||
* in the import_table.
|
||||
* @param deploy_id to search the id for
|
||||
* @return -1 if not found or VMID
|
||||
*
|
||||
*/
|
||||
int get_vmid(const string& deploy_id);
|
||||
|
||||
/**
|
||||
* Function to get the IDs of running VMs
|
||||
* @param oids a vector that contains the IDs
|
||||
@ -199,8 +208,14 @@ public:
|
||||
* @return 0 on success
|
||||
*/
|
||||
static int bootstrap(SqlDB * _db)
|
||||
{
|
||||
return VirtualMachine::bootstrap(_db);
|
||||
{
|
||||
int rc;
|
||||
ostringstream oss_import(import_db_bootstrap);
|
||||
|
||||
rc = VirtualMachine::bootstrap(_db);
|
||||
rc += _db->exec(oss_import);
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -334,9 +349,30 @@ private:
|
||||
static float _default_mem_cost;
|
||||
|
||||
/**
|
||||
* Callback used in calculate_showback
|
||||
* Callback used to get an int in the DB it is used by VM Pool in:
|
||||
* - calculate_showback (min_stime)
|
||||
* - get_vmid (vmid)
|
||||
*/
|
||||
int min_stime_cb(void * _min_stime, int num, char **values, char **names);
|
||||
int db_int_cb(void * _min_stime, int num, char **values, char **names);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Virtual Machine ID - Deploy ID index for imported VMs
|
||||
// The index is managed by the VirtualMachinePool
|
||||
// -------------------------------------------------------------------------
|
||||
static const char * import_table;
|
||||
|
||||
static const char * import_db_names;
|
||||
|
||||
static const char * import_db_bootstrap;
|
||||
|
||||
/**
|
||||
* Insert deploy_id - vmid index.
|
||||
* @param replace will replace and not insert
|
||||
* @return 0 on success
|
||||
*/
|
||||
int insert_index(const string& deploy_id, int vm_id, bool replace);
|
||||
|
||||
void drop_index(const string& deploy_id);
|
||||
};
|
||||
|
||||
#endif /*VIRTUAL_MACHINE_POOL_H_*/
|
||||
|
@ -215,6 +215,87 @@ cmd=CommandParser::CmdParser.new(ARGV) do
|
||||
exit 0
|
||||
end
|
||||
|
||||
vms_desc = <<-EOT.unindent
|
||||
Import vCenter running Virtual Machines into OpenNebula
|
||||
EOT
|
||||
|
||||
command :vms, vms_desc, :options=>[ VCENTER, USER, PASS ] do
|
||||
if options[:vuser].nil? ||
|
||||
options[:vpass].nil? ||
|
||||
options[:vcenter].nil?
|
||||
STDERR.puts "vCenter connection parameters are mandatory to import"\
|
||||
" VM templates:\n"\
|
||||
"\t --vcenter vCenter hostname\n"\
|
||||
"\t --vuser username to login in vcenter\n"\
|
||||
"\t --vpass password for the user"
|
||||
exit -1
|
||||
end
|
||||
|
||||
begin
|
||||
STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."
|
||||
|
||||
vc = VCenterDriver::VIClient.new_connection(
|
||||
:user => options[:vuser],
|
||||
:password => options[:vpass],
|
||||
:host => options[:vcenter])
|
||||
|
||||
STDOUT.print "done!\n\n"
|
||||
|
||||
STDOUT.print "Looking for running Virtual Machines..."
|
||||
|
||||
rs = vc.running_vms
|
||||
|
||||
STDOUT.print "done!\n"
|
||||
|
||||
rs.each {|dc, tmps|
|
||||
STDOUT.print "\nDo you want to process datacenter #{dc} [y/n]? "
|
||||
|
||||
next if STDIN.gets.strip.downcase != 'y'
|
||||
|
||||
if tmps.empty?
|
||||
STDOUT.print " No new running Virtual Machines found in"\
|
||||
" #{dc}...\n\n"
|
||||
next
|
||||
end
|
||||
|
||||
tmps.each{ |v|
|
||||
STDOUT.print "\n * Running Virtual Machine found:\n"\
|
||||
" - Name : #{v[:name]}\n"\
|
||||
" - UUID : #{v[:uuid]}\n"\
|
||||
" - Cluster: #{v[:host]}\n"\
|
||||
" Import this Virtual Machine [y/n]? "
|
||||
|
||||
next if STDIN.gets.strip.downcase != 'y'
|
||||
|
||||
one_v = ::OpenNebula::VirtualMachine.new(
|
||||
::OpenNebula::VirtualMachine.build_xml, vc.one)
|
||||
|
||||
rc = one_v.allocate(v[:one])
|
||||
|
||||
if ::OpenNebula.is_error?(rc)
|
||||
STDOUT.puts " Error creating Virtual Machine: "\
|
||||
"#{rc.message}\n"
|
||||
end
|
||||
|
||||
rc = one_v.deploy v[:host_id]
|
||||
|
||||
if ::OpenNebula.is_error?(rc)
|
||||
STDOUT.puts " Error creating Virtual Machine: "\
|
||||
"#{rc.message}\n"
|
||||
else
|
||||
STDOUT.puts " OpenNebula VM #{one_v.id} "\
|
||||
"created!\n"
|
||||
end
|
||||
}
|
||||
}
|
||||
rescue Exception => e
|
||||
STDOUT.puts "error: #{e.message}"
|
||||
exit -1
|
||||
end
|
||||
|
||||
exit 0
|
||||
end
|
||||
|
||||
network_desc = <<-EOT.unindent
|
||||
Import vCenter networks into OpenNebula
|
||||
EOT
|
||||
|
@ -74,6 +74,62 @@ error:
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DispatchManager::import (
|
||||
VirtualMachine * vm)
|
||||
{
|
||||
ostringstream oss;
|
||||
int vid;
|
||||
|
||||
if ( vm == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
vid = vm->get_oid();
|
||||
|
||||
if ( vm->get_state() != VirtualMachine::PENDING &&
|
||||
vm->get_state() != VirtualMachine::HOLD )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Nebula& nd = Nebula::instance();
|
||||
HostPool * hpool = nd.get_hpool();
|
||||
|
||||
time_t the_time = time(0);
|
||||
int cpu, mem, disk;
|
||||
|
||||
vm->get_requirements(cpu, mem, disk);
|
||||
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
|
||||
vm->set_state(VirtualMachine::ACTIVE);
|
||||
|
||||
vm->set_state(VirtualMachine::RUNNING);
|
||||
|
||||
vmpool->update(vm);
|
||||
|
||||
vm->set_stime(the_time);
|
||||
|
||||
vm->set_prolog_stime(the_time);
|
||||
vm->set_prolog_etime(the_time);
|
||||
|
||||
vm->set_running_stime(the_time);
|
||||
|
||||
vm->set_last_poll(0);
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->log("LCM", Log::INFO, "New VM state is RUNNING");
|
||||
|
||||
vm->unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int DispatchManager::migrate(
|
||||
VirtualMachine * vm)
|
||||
{
|
||||
|
@ -345,6 +345,14 @@ int Host::update_info(Template &tmpl,
|
||||
|
||||
rc = vatt->vector_value("ID", vmid);
|
||||
|
||||
if (rc == 0 && vmid == -1) //Check if it is an imported
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
VirtualMachinePool * vmpool = nd.get_vmpool();
|
||||
|
||||
vmid = vmpool->get_vmid(vatt->vector_value("DEPLOY_ID"));
|
||||
}
|
||||
|
||||
if (rc == 0 && vmid != -1)
|
||||
{
|
||||
if (tmp_lost_vms.erase(vmid) == 1) //Good, known
|
||||
@ -358,23 +366,41 @@ int Host::update_info(Template &tmpl,
|
||||
// Reported as zombie at least 2 times?
|
||||
if (prev_tmp_zombie.count(vmid) == 1)
|
||||
{
|
||||
string zname;
|
||||
|
||||
if (num_zombies++ > 0)
|
||||
{
|
||||
zombie << ", ";
|
||||
}
|
||||
|
||||
zombie << vatt->vector_value("DEPLOY_ID");
|
||||
zname = vatt->vector_value("VM_NAME");
|
||||
|
||||
if (zname.empty())
|
||||
{
|
||||
zname = vatt->vector_value("DEPLOY_ID");
|
||||
}
|
||||
|
||||
zombie << zname;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rc == 0) //not ours
|
||||
{
|
||||
string wname;
|
||||
|
||||
if (num_wilds++ > 0)
|
||||
{
|
||||
wild << ", ";
|
||||
}
|
||||
|
||||
wild << vatt->vector_value("DEPLOY_ID");
|
||||
wname = vatt->vector_value("VM_NAME");
|
||||
|
||||
if (wname.empty())
|
||||
{
|
||||
wname = vatt->vector_value("DEPLOY_ID");
|
||||
}
|
||||
|
||||
wild << wname;
|
||||
}
|
||||
|
||||
delete *it;
|
||||
|
@ -640,6 +640,7 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
int id = xmlrpc_c::value_int(paramList.getInt(1));
|
||||
int hid = xmlrpc_c::value_int(paramList.getInt(2));
|
||||
bool enforce = false;
|
||||
bool imported= false;
|
||||
int ds_id = -1;
|
||||
|
||||
if ( paramList.size() > 3 )
|
||||
@ -688,6 +689,10 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
{
|
||||
ds_id = vm->get_ds_id();
|
||||
}
|
||||
else if (!vm->get_deploy_id().empty()) //deploy_id && not a Stopped VM
|
||||
{
|
||||
imported = true;
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
@ -795,7 +800,14 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
return;
|
||||
}
|
||||
|
||||
dm->deploy(vm);
|
||||
if (!imported)
|
||||
{
|
||||
dm->deploy(vm);
|
||||
}
|
||||
else
|
||||
{
|
||||
dm->import(vm);
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
|
@ -154,6 +154,10 @@ var create_host_tmpl =
|
||||
<div class="vcenter_templates">\
|
||||
</div>\
|
||||
<br>\
|
||||
<br>\
|
||||
<div class="vcenter_vms">\
|
||||
</div>\
|
||||
<br>\
|
||||
<div class="vcenter_networks">\
|
||||
</div>\
|
||||
<div class="row import_vcenter_clusters_div hidden">\
|
||||
@ -1149,6 +1153,112 @@ function fillVCenterTemplates(opts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Retrieve the list of running VMs from vCenter and fill the container with them
|
||||
|
||||
opts = {
|
||||
datacenter: "Datacenter Name",
|
||||
cluster: "Cluster Name",
|
||||
container: Jquery div to inject the html,
|
||||
vcenter_user: vCenter Username,
|
||||
vcenter_password: vCenter Password,
|
||||
vcenter_host: vCenter Host
|
||||
}
|
||||
*/
|
||||
function fillVCenterVMs(opts) {
|
||||
var path = '/vcenter/vms';
|
||||
opts.container.html(generateAdvancedSection({
|
||||
html_id: path,
|
||||
title: tr("Running VMs"),
|
||||
content: '<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
|
||||
'<i class="fa fa-cloud fa-stack-2x"></i>'+
|
||||
'<i class="fa fa-spinner fa-spin fa-stack-1x fa-inverse"></i>'+
|
||||
'</span>'
|
||||
}))
|
||||
|
||||
$('a', opts.container).trigger("click")
|
||||
|
||||
$.ajax({
|
||||
url: path,
|
||||
type: "GET",
|
||||
data: {timeout: false},
|
||||
dataType: "json",
|
||||
headers: {
|
||||
"X_VCENTER_USER": opts.vcenter_user,
|
||||
"X_VCENTER_PASSWORD": opts.vcenter_password,
|
||||
"X_VCENTER_HOST": opts.vcenter_host
|
||||
},
|
||||
success: function(response){
|
||||
$(".content", opts.container).html("");
|
||||
|
||||
$('<div class="row">' +
|
||||
'<div class="large-12 columns">' +
|
||||
'<p style="color: #999">' + tr("Please select the vCenter running VMs to be imported to OpenNebula.") + '</p>' +
|
||||
'</div>' +
|
||||
'</div>').appendTo($(".content", opts.container))
|
||||
|
||||
$.each(response, function(datacenter_name, vms){
|
||||
$('<div class="row">' +
|
||||
'<div class="large-12 columns">' +
|
||||
'<h5>' +
|
||||
datacenter_name + ' ' + tr("DataCenter") +
|
||||
'</h5>' +
|
||||
'</div>' +
|
||||
'</div>').appendTo($(".content", opts.container))
|
||||
|
||||
if (vms.length == 0) {
|
||||
$('<div class="row">' +
|
||||
'<div class="large-12 columns">' +
|
||||
'<label>' +
|
||||
tr("No new running VMs found in this DataCenter") +
|
||||
'</label>' +
|
||||
'</div>' +
|
||||
'</div>').appendTo($(".content", opts.container))
|
||||
} else {
|
||||
$.each(vms, function(id, vm){
|
||||
if (vm.host_id === parseInt(vm.host_id, 10)) {
|
||||
var trow = $('<div class="vcenter_vm">' +
|
||||
'<div class="row">' +
|
||||
'<div class="large-10 columns">' +
|
||||
'<label>' +
|
||||
'<input type="checkbox" class="vm_name" checked/> ' +
|
||||
vm.name + ' <span style="color: #999">' + vm.host + '</span>' +
|
||||
'</vm>' +
|
||||
'<div class="large-12 columns vcenter_vm_response">'+
|
||||
'</div>'+
|
||||
'</div>' +
|
||||
'<div class="large-2 columns vcenter_vm_result">'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'</div>').appendTo($(".content", opts.container))
|
||||
|
||||
$(".vm_name", trow).data("vm_name", vm.name)
|
||||
$(".vm_name", trow).data("one_vm", vm.one)
|
||||
$(".vm_name", trow).data("vm_to_host", vm.host_id)
|
||||
}
|
||||
});
|
||||
|
||||
if ($(".vcenter_vm").length == 0) {
|
||||
$('<div class="row">' +
|
||||
'<div class="large-12 columns">' +
|
||||
'<label>' +
|
||||
tr("No new running VMs found in this DataCenter") +
|
||||
'</label>' +
|
||||
'</div>' +
|
||||
'</div>').appendTo($(".content", opts.container))
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
error: function(response){
|
||||
opts.container.html("");
|
||||
onError({}, OpenNebula.Error(response));
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
Retrieve the list of networks from vCenter and fill the container with them
|
||||
|
||||
@ -1443,6 +1553,7 @@ function setupCreateHostDialog(){
|
||||
});
|
||||
|
||||
var templates_container = $(".vcenter_templates", $create_host_dialog);
|
||||
var vms_container = $(".vcenter_vms", $create_host_dialog);
|
||||
var networks_container = $(".vcenter_networks", $create_host_dialog);
|
||||
|
||||
var vcenter_user = $("#vcenter_user", $create_host_dialog).val();
|
||||
@ -1456,6 +1567,13 @@ function setupCreateHostDialog(){
|
||||
vcenter_host: vcenter_host
|
||||
});
|
||||
|
||||
fillVCenterVMs({
|
||||
container: vms_container,
|
||||
vcenter_user: vcenter_user,
|
||||
vcenter_password: vcenter_password,
|
||||
vcenter_host: vcenter_host
|
||||
});
|
||||
|
||||
fillVCenterNetworks({
|
||||
container: networks_container,
|
||||
vcenter_user: vcenter_user,
|
||||
@ -1576,6 +1694,60 @@ function setupCreateHostDialog(){
|
||||
});
|
||||
})
|
||||
|
||||
$.each($(".vm_name:checked", $create_host_dialog), function(){
|
||||
var vm_context = $(this).closest(".vcenter_vm");
|
||||
|
||||
$(".vcenter_vm_result:not(.success)", vm_context).html(
|
||||
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
|
||||
'<i class="fa fa-cloud fa-stack-2x"></i>'+
|
||||
'<i class="fa fa-spinner fa-spin fa-stack-1x fa-inverse"></i>'+
|
||||
'</span>');
|
||||
|
||||
var vm_json = {
|
||||
"vm": {
|
||||
"vm_raw": $(this).data("one_vm")
|
||||
}
|
||||
};
|
||||
|
||||
var host_id_to_deploy = $(this).data("vm_to_host");
|
||||
|
||||
OpenNebula.VM.create({
|
||||
timeout: true,
|
||||
data: vm_json,
|
||||
success: function(request, response) {
|
||||
OpenNebula.Helper.clear_cache("VM");
|
||||
|
||||
var extra_info = {};
|
||||
|
||||
extra_info['host_id'] = host_id_to_deploy;
|
||||
extra_info['ds_id'] = -1;
|
||||
extra_info['enforce'] = false;
|
||||
|
||||
Sunstone.runAction("VM.deploy_action", response.VM.ID, extra_info);
|
||||
|
||||
$(".vcenter_vm_result", vm_context).addClass("success").html(
|
||||
'<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
|
||||
'<i class="fa fa-cloud fa-stack-2x"></i>'+
|
||||
'<i class="fa fa-check fa-stack-1x fa-inverse"></i>'+
|
||||
'</span>');
|
||||
|
||||
$(".vcenter_vm_response", vm_context).html('<p style="font-size:12px" class="running-color">'+
|
||||
tr("VM imported successfully")+' ID:'+response.VM.ID+
|
||||
'</p>');
|
||||
},
|
||||
error: function (request, error_json){
|
||||
$(".vcenter_vm_response", vm_context).html('<span class="fa-stack fa-2x" style="color: #dfdfdf">'+
|
||||
'<i class="fa fa-cloud fa-stack-2x"></i>'+
|
||||
'<i class="fa fa-warning fa-stack-1x fa-inverse"></i>'+
|
||||
'</span>');
|
||||
|
||||
$(".vcenter_vm_response", vm_context).html('<p style="font-size:12px" class="error-color">'+
|
||||
(error_json.error.message || tr("Cannot contact server: is it running and reachable?"))+
|
||||
'</p>');
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
$.each($(".network_name:checked", $create_host_dialog), function(){
|
||||
var network_context = $(this).closest(".vcenter_network");
|
||||
|
||||
|
@ -1831,6 +1831,43 @@ function getName(id,dataTable,name_col){
|
||||
return name;
|
||||
};
|
||||
|
||||
function getHostIdFromName(hostName) {
|
||||
getColumnValue({
|
||||
dataTable: dataTable_hosts,
|
||||
columnFilterIndex: 2, // Name
|
||||
columnFilterValue: hostName,
|
||||
columnResultIndex: 1 // ID
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the value of the columnResultIndex column of the row
|
||||
whose columnFilterIndex column has the columnFilterValue value
|
||||
|
||||
opts = {
|
||||
dataTable: datatable to get the info from
|
||||
columnFilterIndex: column that will be filtered
|
||||
columnFilterValue: value to filter
|
||||
columnResultIndex: value to be returned
|
||||
}
|
||||
*/
|
||||
function getColumnValue(opts) {
|
||||
if (typeof(opts.dataTable) == "undefined") {
|
||||
return false;
|
||||
};
|
||||
|
||||
var result = false;
|
||||
|
||||
$.each(opts.dataTable.fnGetData(), function(){
|
||||
if (opts.columnFilterValue == this[opts.columnFilterIndex]) {
|
||||
result = this[opts.columnResultIndex];
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// A more general version of the above.
|
||||
// Search a datatable record matching the filter_str in the filter_col. Returns
|
||||
// the value of that record in the desired value column.
|
||||
|
@ -87,6 +87,26 @@ get '/vcenter/templates' do
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
get '/vcenter/vms' do
|
||||
begin
|
||||
vms = vcenter_client.running_vms(
|
||||
$cloud_auth.client(session[:user], session[:active_zone_endpoint]))
|
||||
if vms.nil?
|
||||
msg = "No datacenter found"
|
||||
logger.error("[vCenter] " + msg)
|
||||
error = Error.new(msg)
|
||||
error 404, error.to_json
|
||||
end
|
||||
|
||||
[200, vms.to_json]
|
||||
rescue Exception => e
|
||||
logger.error("[vCenter] " + e.message)
|
||||
error = Error.new(e.message)
|
||||
error 403, error.to_json
|
||||
end
|
||||
end
|
||||
|
||||
get '/vcenter/networks' do
|
||||
begin
|
||||
networks = vcenter_client.vcenter_networks(
|
||||
|
@ -438,6 +438,21 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
goto error_graphics;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Get and set DEPLOY_ID for imported VMs
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
user_obj_template->get("IMPORT_VM_ID", value);
|
||||
user_obj_template->erase("IMPORT_VM_ID");
|
||||
|
||||
if (!value.empty())
|
||||
{
|
||||
deploy_id = value;
|
||||
obj_template->add("IMPORTED", "YES");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
parse_well_known_attributes();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "VirtualMachineHook.h"
|
||||
|
||||
#include "NebulaLog.h"
|
||||
#include "Nebula.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@ -29,6 +30,16 @@ bool VirtualMachinePool::_submit_on_hold;
|
||||
float VirtualMachinePool::_default_cpu_cost;
|
||||
float VirtualMachinePool::_default_mem_cost;
|
||||
|
||||
|
||||
const char * VirtualMachinePool::import_table = "vm_import";
|
||||
|
||||
const char * VirtualMachinePool::import_db_names = "deploy_id, vmid";
|
||||
|
||||
const char * VirtualMachinePool::import_db_bootstrap =
|
||||
"CREATE TABLE IF NOT EXISTS vm_import "
|
||||
"(deploy_id VARCHAR(128), vmid INTEGER, PRIMARY KEY(deploy_id))";
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
@ -246,6 +257,54 @@ VirtualMachinePool::VirtualMachinePool(
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachinePool::insert_index(const string& deploy_id, int vmid,
|
||||
bool replace)
|
||||
{
|
||||
ostringstream oss;
|
||||
char * deploy_name = db->escape_str(deploy_id.c_str());
|
||||
|
||||
if (deploy_name == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (replace)
|
||||
{
|
||||
oss << "REPLACE ";
|
||||
}
|
||||
else
|
||||
{
|
||||
oss << "INSERT ";
|
||||
}
|
||||
|
||||
oss << "INTO " << import_table << " ("<< import_db_names <<") "
|
||||
<< " VALUES ('" << deploy_name << "'," << vmid << ")";
|
||||
|
||||
db->free_str(deploy_name);
|
||||
|
||||
return db->exec(oss);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachinePool::drop_index(const string& deploy_id)
|
||||
{
|
||||
ostringstream oss;
|
||||
char * deploy_name = db->escape_str(deploy_id.c_str());
|
||||
|
||||
if (deploy_name == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
oss << "DELETE FROM " << import_table << " WHERE deploy_id='"
|
||||
<< deploy_name << "'";
|
||||
|
||||
db->exec(oss);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachinePool::allocate (
|
||||
int uid,
|
||||
int gid,
|
||||
@ -258,12 +317,14 @@ int VirtualMachinePool::allocate (
|
||||
bool on_hold)
|
||||
{
|
||||
VirtualMachine * vm;
|
||||
|
||||
string deploy_id;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Build a new Virtual Machine object
|
||||
// ------------------------------------------------------------------------
|
||||
vm = new VirtualMachine(-1, uid, gid, uname, gname, umask, vm_template);
|
||||
|
||||
|
||||
if ( _submit_on_hold == true || on_hold )
|
||||
{
|
||||
vm->state = VirtualMachine::HOLD;
|
||||
@ -273,12 +334,43 @@ int VirtualMachinePool::allocate (
|
||||
vm->state = VirtualMachine::PENDING;
|
||||
}
|
||||
|
||||
vm->user_obj_template->get("IMPORT_VM_ID", deploy_id);
|
||||
|
||||
if (!deploy_id.empty())
|
||||
{
|
||||
vm->state = VirtualMachine::HOLD;
|
||||
|
||||
if (insert_index(deploy_id, -1, false) == -1) //Set import in progress
|
||||
{
|
||||
delete vm;
|
||||
|
||||
error_str = "Virtual Machine " + deploy_id + " already imported.";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Insert the Object in the pool
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
*oid = PoolSQL::allocate(vm, error_str);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Insert the deploy_id - vmid index for imported VMs
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if (!deploy_id.empty())
|
||||
{
|
||||
if (*oid >= 0)
|
||||
{
|
||||
insert_index(deploy_id, *oid, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
drop_index(deploy_id);
|
||||
}
|
||||
}
|
||||
|
||||
return *oid;
|
||||
}
|
||||
|
||||
@ -466,14 +558,14 @@ int VirtualMachinePool::dump_monitoring(
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachinePool::min_stime_cb(void * _min_stime, int num, char **values, char **names)
|
||||
int VirtualMachinePool::db_int_cb(void * _int_output, int num, char **values, char **names)
|
||||
{
|
||||
if ( num == 0 || values == 0 || values[0] == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
*static_cast<int*>(_min_stime) = atoi(values[0]);
|
||||
*static_cast<int*>(_int_output) = atoi(values[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -481,6 +573,33 @@ int VirtualMachinePool::min_stime_cb(void * _min_stime, int num, char **values,
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int VirtualMachinePool::get_vmid (const string& deploy_id)
|
||||
{
|
||||
int rc;
|
||||
int vmid = -1;
|
||||
ostringstream oss;
|
||||
|
||||
set_callback(static_cast<Callbackable::Callback>(&VirtualMachinePool::db_int_cb),
|
||||
static_cast<void *>(&vmid));
|
||||
|
||||
oss << "SELECT vmid FROM " << import_table
|
||||
<< " WHERE deploy_id = '" << db->escape_str(deploy_id.c_str()) << "'";
|
||||
|
||||
rc = db->exec(oss, this);
|
||||
|
||||
unset_callback();
|
||||
|
||||
if (rc != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return vmid;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef SBDEBUG
|
||||
static string put_time(tm tmp_tm)
|
||||
{
|
||||
@ -603,7 +722,7 @@ int VirtualMachinePool::calculate_showback(
|
||||
{
|
||||
// Set start time to the lowest stime from the history records
|
||||
|
||||
set_callback(static_cast<Callbackable::Callback>(&VirtualMachinePool::min_stime_cb),
|
||||
set_callback(static_cast<Callbackable::Callback>(&VirtualMachinePool::db_int_cb),
|
||||
static_cast<void *>(&start_time));
|
||||
|
||||
oss << "SELECT MIN(stime) FROM " << History::table;
|
||||
@ -905,3 +1024,6 @@ int VirtualMachinePool::calculate_showback(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -246,6 +246,87 @@ class VIClient
|
||||
return vm_templates
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Builds a hash with the Datacenter / Virtual Machines for this VCenter
|
||||
# @param one_client [OpenNebula::Client] Use this client instead of @one
|
||||
# @return [Hash] in the form
|
||||
# { dc_name [String] => }
|
||||
########################################################################
|
||||
def running_vms(one_client=nil)
|
||||
running_vms = {}
|
||||
|
||||
vmpool = OpenNebula::VirtualMachinePool.new(
|
||||
(one_client||@one), OpenNebula::Pool::INFO_ALL)
|
||||
rc = vmpool.info
|
||||
|
||||
hostpool = OpenNebula::HostPool.new((one_client||@one))
|
||||
rc = hostpool.info
|
||||
# TODO check error
|
||||
|
||||
datacenters = get_entities(@root, 'Datacenter')
|
||||
|
||||
datacenters.each { |dc|
|
||||
vms = get_entities(dc.vmFolder, 'VirtualMachine')
|
||||
ccrs = get_entities(dc.hostFolder, 'ClusterComputeResource')
|
||||
|
||||
tmp = vms.select { |v|
|
||||
# Get rid of VM Templates and VMs not in running state
|
||||
v.config &&
|
||||
v.config.template != true &&
|
||||
v.summary.runtime.powerState == "poweredOn"
|
||||
}
|
||||
|
||||
one_tmp = []
|
||||
|
||||
tmp.each { |v|
|
||||
vi_tmp = VCenterVm.new(self, v)
|
||||
|
||||
container_hostname = vi_tmp.vm.runtime.host.parent.name
|
||||
|
||||
cluster_name = ccrs.collect { |c|
|
||||
found_host=c.host.select {|h|
|
||||
h.parent.name == container_hostname}
|
||||
found_host.first.parent.name if found_host.size > 0
|
||||
}.first
|
||||
|
||||
if !vmpool["VM/USER_TEMPLATE/PUBLIC_CLOUD[\
|
||||
TYPE=\"vcenter\" \
|
||||
and VM_TEMPLATE=\"#{vi_tmp.vm.config.uuid}\"]"]
|
||||
|
||||
host_id = name_to_id(container_hostname,hostpool,"HOST")[1]
|
||||
|
||||
one_tmp << {
|
||||
:name => vi_tmp.vm.name,
|
||||
:uuid => vi_tmp.vm.config.uuid,
|
||||
:host => container_hostname,
|
||||
:host_id => host_id,
|
||||
:one => vi_tmp.vm_to_one
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
running_vms[dc.name] = one_tmp
|
||||
}
|
||||
|
||||
return running_vms
|
||||
end
|
||||
|
||||
def name_to_id(name, pool, ename)
|
||||
objects=pool.select {|object| object.name==name }
|
||||
|
||||
if objects.length>0
|
||||
if objects.length>1
|
||||
return -1, "There are multiple #{ename}s with name #{name}."
|
||||
else
|
||||
result = objects.first.id
|
||||
end
|
||||
else
|
||||
return -1, "#{ename} named #{name} not found."
|
||||
end
|
||||
|
||||
return 0, result
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Builds a hash with the Datacenter / CCR (Distributed)Networks
|
||||
# for this VCenter
|
||||
@ -541,9 +622,12 @@ class VCenterHost < ::OpenNebula::Host
|
||||
vm = VCenterVm.new(@client, v)
|
||||
vm.monitor
|
||||
|
||||
next if !vm.vm.config
|
||||
|
||||
str_info << "\nVM = ["
|
||||
str_info << "ID=#{number},"
|
||||
str_info << "DEPLOY_ID=\"#{name}\","
|
||||
str_info << "DEPLOY_ID=\"#{vm.vm.config.uuid}\","
|
||||
str_info << "VM_NAME=\"#{name}\","
|
||||
str_info << "POLL=\"#{vm.info}\"]"
|
||||
}
|
||||
|
||||
@ -948,6 +1032,35 @@ class VCenterVm
|
||||
return str
|
||||
end
|
||||
|
||||
########################################################################
|
||||
# Generates an OpenNebula VirtualMachine for this VCenterVm
|
||||
#
|
||||
#
|
||||
########################################################################
|
||||
def vm_to_one
|
||||
str = "NAME = \"#{@vm.name}\"\n"\
|
||||
"CPU = \"#{@vm.config.hardware.numCPU}\"\n"\
|
||||
"vCPU = \"#{@vm.config.hardware.numCPU}\"\n"\
|
||||
"MEMORY = \"#{@vm.config.hardware.memoryMB}\"\n"\
|
||||
"HYPERVISOR = \"vcenter\"\n"\
|
||||
"PUBLIC_CLOUD = [\n"\
|
||||
" TYPE =\"vcenter\",\n"\
|
||||
" VM_TEMPLATE =\"#{@vm.config.uuid}\"\n"\
|
||||
"]\n"\
|
||||
"IMPORT_VM_ID = \"#{@vm.config.uuid}\"\n"\
|
||||
"SCHED_REQUIREMENTS=\"NAME=\\\"#{@vm.runtime.host.parent.name}\\\"\"\n"
|
||||
|
||||
if @vm.config.annotation.nil? || @vm.config.annotation.empty?
|
||||
str << "DESCRIPTION = \"vCenter Virtual Machine imported by OpenNebula"\
|
||||
" from Cluster #{@vm.runtime.host.parent.name}\"\n"
|
||||
else
|
||||
notes = @vm.config.annotation.gsub("\\", "\\\\").gsub("\"", "\\\"")
|
||||
str << "DESCRIPTION = \"#{notes}\"\n"
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
########################################################################
|
||||
|
Loading…
x
Reference in New Issue
Block a user