mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-21 14:50:08 +03:00
Merge branch 'feature-3028'
This commit is contained in:
commit
2fff41d8d0
@ -379,13 +379,15 @@ public:
|
||||
* @param cpu needed by the VM (percentage)
|
||||
* @param mem needed by the VM (in KB)
|
||||
* @param disk needed by the VM
|
||||
* @param pci devices needed by th VM
|
||||
* @return 0 on success
|
||||
*/
|
||||
void add_capacity(int vm_id, long long cpu, long long mem, long long disk)
|
||||
void add_capacity(int vm_id, long long cpu, long long mem, long long disk,
|
||||
vector<Attribute *> pci)
|
||||
{
|
||||
if ( vm_collection.add_collection_id(vm_id) == 0 )
|
||||
{
|
||||
host_share.add(cpu,mem,disk);
|
||||
host_share.add(vm_id, cpu, mem, disk, pci);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -404,13 +406,15 @@ public:
|
||||
* @param cpu used by the VM (percentage)
|
||||
* @param mem used by the VM (in KB)
|
||||
* @param disk used by the VM
|
||||
* @param pci devices needed by th VM
|
||||
* @return 0 on success
|
||||
*/
|
||||
void del_capacity(int vm_id, long long cpu, long long mem, long long disk)
|
||||
void del_capacity(int vm_id, long long cpu, long long mem, long long disk,
|
||||
vector<Attribute *> pci)
|
||||
{
|
||||
if ( vm_collection.del_collection_id(vm_id) == 0 )
|
||||
{
|
||||
host_share.del(cpu,mem,disk);
|
||||
host_share.del(cpu, mem, disk, pci);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -440,11 +444,14 @@ public:
|
||||
* @param cpu needed by the VM (percentage)
|
||||
* @param mem needed by the VM (in Kb)
|
||||
* @param disk needed by the VM
|
||||
* @param pci devices needed by the VM
|
||||
* @param error Returns the error reason, if any
|
||||
* @return true if the share can host the VM
|
||||
*/
|
||||
bool test_capacity(long long cpu, long long mem, long long disk)
|
||||
bool test_capacity(long long cpu, long long mem, long long disk,
|
||||
vector<Attribute *> &pci, string& error)
|
||||
{
|
||||
return host_share.test(cpu, mem, disk);
|
||||
return host_share.test(cpu, mem, disk, pci, error);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,17 +123,19 @@ public:
|
||||
* @param cpu amount of CPU, in percentage
|
||||
* @param mem amount of main memory, in KB
|
||||
* @param disk amount of disk
|
||||
* @param pci devices requested by the VM
|
||||
*
|
||||
* @return 0 on success -1 in case of failure
|
||||
*/
|
||||
int add_capacity(int oid, int vm_id, int cpu, int mem, int disk)
|
||||
int add_capacity(int oid, int vm_id, int cpu, int mem, int disk,
|
||||
vector<Attribute *> pci)
|
||||
{
|
||||
int rc = 0;
|
||||
Host * host = get(oid, true);
|
||||
|
||||
if ( host != 0 )
|
||||
{
|
||||
host->add_capacity(vm_id, cpu, mem, disk);
|
||||
host->add_capacity(vm_id, cpu, mem, disk, pci);
|
||||
|
||||
update(host);
|
||||
|
||||
@ -154,14 +156,16 @@ public:
|
||||
* @param cpu amount of CPU
|
||||
* @param mem amount of main memory
|
||||
* @param disk amount of disk
|
||||
* @param pci devices requested by the VM
|
||||
*/
|
||||
void del_capacity(int oid, int vm_id, int cpu, int mem, int disk)
|
||||
void del_capacity(int oid, int vm_id, int cpu, int mem, int disk,
|
||||
vector<Attribute *> pci)
|
||||
{
|
||||
Host * host = get(oid, true);
|
||||
|
||||
if ( host != 0 )
|
||||
{
|
||||
host->del_capacity(vm_id, cpu, mem, disk);
|
||||
host->del_capacity(vm_id, cpu, mem, disk, pci);
|
||||
|
||||
update(host);
|
||||
|
||||
|
@ -20,22 +20,179 @@
|
||||
#include "ObjectXML.h"
|
||||
#include "Template.h"
|
||||
#include <time.h>
|
||||
|
||||
using namespace std;
|
||||
#include <set>
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
class HostShareTemplate : public Template
|
||||
class HostShareDatastore : public Template
|
||||
{
|
||||
public:
|
||||
HostShareTemplate() : Template(false,'=',"DATASTORES"){};
|
||||
HostShareDatastore() : Template(false, '=', "DATASTORES"){};
|
||||
|
||||
~HostShareTemplate(){};
|
||||
virtual ~HostShareDatastore(){};
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/**
|
||||
* This class represents a PCI DEVICE list for the host. The list is in the
|
||||
* form:
|
||||
* <PCI>
|
||||
* <DOMAIN> PCI address domain
|
||||
* <BUS> PCI address bus
|
||||
* <SLOT> PCI address slot
|
||||
* <FUNCTION> PCI address function
|
||||
* <ADDRESS> PCI address, bus, slot and function
|
||||
* <VENDOR> ID of PCI device vendor
|
||||
* <DEVICE> ID of PCI device
|
||||
* <CLASS> ID of PCI device class
|
||||
* <VMID> ID using this device, -1 if free
|
||||
*
|
||||
* The monitor probe may report additional information such as VENDOR_NAME,
|
||||
* DEVICE_NAME, CLASS_NAME...
|
||||
*/
|
||||
class HostSharePCI : public Template
|
||||
{
|
||||
public:
|
||||
|
||||
HostSharePCI() : Template(false, '=', "PCI_DEVICES"){};
|
||||
|
||||
virtual ~HostSharePCI()
|
||||
{
|
||||
map<string, PCIDevice *>::iterator it;
|
||||
|
||||
for (it=pci_devices.begin(); it != pci_devices.end(); it++)
|
||||
{
|
||||
delete it->second;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds the devices list from its XML representation. This function
|
||||
* is used when importing it from the DB.
|
||||
* @param node xmlNode for the template
|
||||
* @return 0 on success
|
||||
*/
|
||||
int from_xml_node(const xmlNodePtr node);
|
||||
|
||||
/**
|
||||
* Test whether this PCI device set has the requested devices available.
|
||||
* @param devs list of requested devices by the VM.
|
||||
* @return true if all the devices are available.
|
||||
*/
|
||||
bool test(vector<Attribute *> &devs) const;
|
||||
|
||||
/**
|
||||
* Assign the requested devices to the given VM. The assigned devices will
|
||||
* be labeled with the VM and the PCI attribute of the VM extended with
|
||||
* the address of the assigned devices.
|
||||
* @param devs list of requested PCI devices, will include address of
|
||||
* assigned devices.
|
||||
* @param vmid of the VM
|
||||
*/
|
||||
void add(vector<Attribute *> &devs, int vmid)
|
||||
{
|
||||
test_set(devs, vmid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the VM assignment from the PCI device list
|
||||
*/
|
||||
void del(const vector<Attribute *> &devs);
|
||||
|
||||
/**
|
||||
* Updates the PCI list with monitor data, it will create or
|
||||
* remove PCIDevices as needed.
|
||||
*/
|
||||
void set_monitorization(vector<Attribute*> &pci_att);
|
||||
|
||||
/**
|
||||
* Prints the PCI device list to an output stream. This function is used
|
||||
* for logging purposes and *not* for generating DB content.
|
||||
*/
|
||||
friend ostream& operator<<(ostream& o, const HostSharePCI& p);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Sets the internal class structures from the template
|
||||
*/
|
||||
int init();
|
||||
|
||||
/**
|
||||
* Test if a PCIDevice matches the vendor, device and class request spec
|
||||
* and can be assigned. If free, it is stored in the assigned set
|
||||
* @param vendor_id id in uint form 0 means *
|
||||
* @param device_id id in uint form 0 means *
|
||||
* @param class_id id in uint form 0 means *
|
||||
* @param pci requested pci device
|
||||
* @param vmid if not -1 it will also assign the PCI device to the VM,
|
||||
* and the pci attribute will be extended with device information.
|
||||
* @param assigned set of addresses already assigned devices, it will
|
||||
* include the selected device if found; useful to iterate.
|
||||
*
|
||||
* @return true if a device was found.
|
||||
*/
|
||||
bool test(unsigned int vendor_id, unsigned int device_id,
|
||||
unsigned int class_id, const VectorAttribute *pci,
|
||||
std::set<string> &assigned) const;
|
||||
|
||||
/**
|
||||
* Test if a PCIDevice matches the vendor, device and class request spec
|
||||
* and can be assigned. It will assign it if requested.
|
||||
* @param vendor_id id in uint form 0 means *
|
||||
* @param device_id id in uint form 0 means *
|
||||
* @param class_id id in uint form 0 means *
|
||||
* @param pci requested pci device
|
||||
* @param vmid if not -1 it will also assign the PCI device to the VM,
|
||||
* and the pci attribute will be extended with device information.
|
||||
* @param assigned set of addresses already assigned devices, it will
|
||||
* include the selected device if found; useful to iterate.
|
||||
*
|
||||
* @return true if a device was found.
|
||||
*/
|
||||
bool test_set(unsigned int vendor_id, unsigned int device_id,
|
||||
unsigned int class_id, VectorAttribute *pci, int vmid,
|
||||
std::set<string> &assigned) const;
|
||||
|
||||
/**
|
||||
* Test if the given list of PCIDevices can be assigned to the VM
|
||||
* @param devs, list of PCI devices
|
||||
* @param vmid if not -1 it will assign the devices to the VM
|
||||
*
|
||||
* @return true if the PCIDevice list can be assigned.
|
||||
*/
|
||||
bool test_set(vector<Attribute *> &devs, int vmid) const;
|
||||
|
||||
/**
|
||||
* Gets a 4 hex digits value from attribute
|
||||
* @param name of the attribute
|
||||
* @pci_device VectorAttribute representing the device
|
||||
* @return the value as unsigned int or 0 if was not found
|
||||
*/
|
||||
static unsigned int get_pci_value(const char * name,
|
||||
const VectorAttribute * pci_device);
|
||||
/**
|
||||
* Internal structure to represent PCI devices for fast look up and
|
||||
* update
|
||||
*/
|
||||
struct PCIDevice
|
||||
{
|
||||
PCIDevice(VectorAttribute * _attrs);
|
||||
|
||||
~PCIDevice(){};
|
||||
|
||||
unsigned int vendor_id;
|
||||
unsigned int device_id;
|
||||
unsigned int class_id;
|
||||
|
||||
int vmid;
|
||||
|
||||
string address;
|
||||
|
||||
VectorAttribute * attrs;
|
||||
};
|
||||
|
||||
map <string, PCIDevice *> pci_devices;
|
||||
};
|
||||
|
||||
/**
|
||||
* The HostShare class. It represents a logical partition of a host...
|
||||
@ -53,16 +210,21 @@ public:
|
||||
|
||||
/**
|
||||
* Add a new VM to this share
|
||||
* @param vmid of the VM
|
||||
* @param cpu requested by the VM, in percentage
|
||||
* @param mem requested by the VM, in KB
|
||||
* @param disk requested by the VM
|
||||
* @param pci_devs requested by the VM
|
||||
*/
|
||||
void add(long long cpu, long long mem, long long disk)
|
||||
void add(int vmid, long long cpu, long long mem, long long disk,
|
||||
vector<Attribute *> pci_devs)
|
||||
{
|
||||
cpu_usage += cpu;
|
||||
mem_usage += mem;
|
||||
disk_usage += disk;
|
||||
|
||||
pci.add(pci_devs, vmid);
|
||||
|
||||
running_vms++;
|
||||
}
|
||||
|
||||
@ -84,13 +246,16 @@ public:
|
||||
* @param cpu requested by the VM
|
||||
* @param mem requested by the VM
|
||||
* @param disk requested by the VM
|
||||
* @param pci_devs requested by the VM
|
||||
*/
|
||||
void del(long long cpu, long long mem, long long disk)
|
||||
void del(long long cpu, long long mem, long long disk, vector<Attribute *> pci_devs)
|
||||
{
|
||||
cpu_usage -= cpu;
|
||||
mem_usage -= mem;
|
||||
disk_usage -= disk;
|
||||
|
||||
pci.del(pci_devs);
|
||||
|
||||
running_vms--;
|
||||
}
|
||||
|
||||
@ -99,15 +264,35 @@ public:
|
||||
* @param cpu requested by the VM
|
||||
* @param mem requested by the VM
|
||||
* @param disk requested by the VM
|
||||
* @param pci_devs requested by the VM
|
||||
* @param error Returns the error reason, if any
|
||||
*
|
||||
* @return true if the share can host the VM or it is the only one
|
||||
* configured
|
||||
*/
|
||||
bool test(long long cpu, long long mem, long long disk) const
|
||||
bool test(long long cpu, long long mem, long long disk,
|
||||
vector<Attribute *>& pci_devs, string& error) const
|
||||
{
|
||||
return (((max_cpu - cpu_usage ) >= cpu) &&
|
||||
((max_mem - mem_usage ) >= mem) &&
|
||||
((max_disk - disk_usage) >= disk));
|
||||
bool pci_fits = pci.test(pci_devs);
|
||||
|
||||
bool fits = (((max_cpu - cpu_usage ) >= cpu) &&
|
||||
((max_mem - mem_usage ) >= mem) &&
|
||||
((max_disk - disk_usage) >= disk)&&
|
||||
pci_fits);
|
||||
|
||||
if (!fits)
|
||||
{
|
||||
if ( pci_fits )
|
||||
{
|
||||
error = "Not enough capacity.";
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Unavailable PCI device.";
|
||||
}
|
||||
}
|
||||
|
||||
return fits;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,6 +310,11 @@ public:
|
||||
|
||||
void set_ds_monitorization(const vector<Attribute*> &ds_att);
|
||||
|
||||
void set_pci_monitorization(vector<Attribute*> &pci_att)
|
||||
{
|
||||
pci.set_monitorization(pci_att);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
long long disk_usage; /**< Disk allocated to VMs (in MB). */
|
||||
@ -145,7 +335,8 @@ private:
|
||||
|
||||
long long running_vms;/**< Number of running VMs in this Host */
|
||||
|
||||
HostShareTemplate ds_template;
|
||||
HostShareDatastore ds;
|
||||
HostSharePCI pci;
|
||||
|
||||
// ----------------------------------------
|
||||
// Friends
|
||||
|
@ -90,10 +90,9 @@ protected:
|
||||
string& tm_mad,
|
||||
RequestAttributes& att);
|
||||
|
||||
bool check_host(int hid,
|
||||
int cpu,
|
||||
int mem,
|
||||
int disk,
|
||||
bool check_host(int hid,
|
||||
bool enforce,
|
||||
VirtualMachine* vm,
|
||||
string& error);
|
||||
|
||||
int add_history(VirtualMachine * vm,
|
||||
|
@ -1222,8 +1222,10 @@ public:
|
||||
* @param cpu
|
||||
* @param memory
|
||||
* @param disk
|
||||
* @param pci_dev
|
||||
*/
|
||||
void get_requirements (int& cpu, int& memory, int& disk);
|
||||
void get_requirements (int& cpu, int& memory, int& disk,
|
||||
vector<Attribute *>& pci_dev);
|
||||
|
||||
/**
|
||||
* Checks if the resize parameters are valid
|
||||
|
@ -847,6 +847,7 @@ IM_PROBES_KVM_PROBES_FILES="src/im_mad/remotes/kvm-probes.d/kvm.rb \
|
||||
src/im_mad/remotes/kvm-probes.d/cpu.sh \
|
||||
src/im_mad/remotes/kvm-probes.d/poll.sh \
|
||||
src/im_mad/remotes/kvm-probes.d/name.sh \
|
||||
src/im_mad/remotes/kvm-probes.d/pci.rb \
|
||||
src/im_mad/remotes/common.d/monitor_ds.sh \
|
||||
src/im_mad/remotes/common.d/version.sh \
|
||||
src/im_mad/remotes/common.d/collectd-client-shepherd.sh"
|
||||
|
@ -413,11 +413,22 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
||||
|
||||
wilds = host.wilds
|
||||
|
||||
begin
|
||||
pcis = [host.to_hash['HOST']['HOST_SHARE']['PCI_DEVICES']['PCI']]
|
||||
pcis = pcis.flatten.compact
|
||||
rescue
|
||||
pcis = nil
|
||||
end
|
||||
|
||||
host.delete_element("TEMPLATE/VM")
|
||||
host.delete_element("TEMPLATE_WILDS")
|
||||
|
||||
puts host.template_str
|
||||
|
||||
if pcis && !pcis.empty?
|
||||
print_pcis(pcis)
|
||||
end
|
||||
|
||||
puts
|
||||
CLIHelper.print_header("WILD VIRTUAL MACHINES", false)
|
||||
puts
|
||||
@ -457,4 +468,43 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
||||
onevm_helper.client=@client
|
||||
onevm_helper.list_pool({:filter=>["HOST=#{host.name}"]}, false)
|
||||
end
|
||||
|
||||
def print_pcis(pcis)
|
||||
puts
|
||||
CLIHelper.print_header("PCI DEVICES", false)
|
||||
puts
|
||||
|
||||
table=CLIHelper::ShowTable.new(nil, self) do
|
||||
column :VM, "Used by VM", :size => 4, :left => false do |d|
|
||||
if d["VMID"] == "-1"
|
||||
""
|
||||
else
|
||||
d["VMID"]
|
||||
end
|
||||
end
|
||||
|
||||
column :ADDR, "PCI Address", :size => 7, :left => true do |d|
|
||||
d["SHORT_ADDRESS"]
|
||||
end
|
||||
|
||||
column :TYPE, "Type", :size => 14, :left => true do |d|
|
||||
d["TYPE"]
|
||||
end
|
||||
|
||||
column :CLASS, "Class", :size => 12, :left => true do |d|
|
||||
d["CLASS_NAME"]
|
||||
end
|
||||
|
||||
column :NAME, "Name", :size => 30, :left => true do |d|
|
||||
d["DEVICE_NAME"]
|
||||
end
|
||||
|
||||
column :VENDOR, "Vendor", :size => 8, :left => true do |d|
|
||||
d["VENDOR_NAME"]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
table.show(pcis)
|
||||
end
|
||||
end
|
||||
|
@ -92,10 +92,11 @@ int DispatchManager::import (
|
||||
|
||||
time_t the_time = time(0);
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
vm->get_requirements(cpu, mem, disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
vm->set_state(VirtualMachine::ACTIVE);
|
||||
|
||||
@ -771,6 +772,8 @@ int DispatchManager::finalize(
|
||||
Host * host;
|
||||
ostringstream oss;
|
||||
|
||||
vector<Attribute *> pci;
|
||||
|
||||
VirtualMachine::VmState state;
|
||||
bool is_public_host = false;
|
||||
int host_id = -1;
|
||||
@ -809,8 +812,8 @@ int DispatchManager::finalize(
|
||||
case VirtualMachine::POWEROFF:
|
||||
int cpu, mem, disk;
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
hpool->del_capacity(vm->get_hid(),vm->get_oid(),cpu,mem,disk,pci);
|
||||
|
||||
if (is_public_host)
|
||||
{
|
||||
|
@ -256,6 +256,7 @@ int Host::update_info(Template &tmpl,
|
||||
vector<Attribute*>::iterator it;
|
||||
vector<Attribute*> vm_att;
|
||||
vector<Attribute*> ds_att;
|
||||
vector<Attribute*> pci_att;
|
||||
vector<Attribute*> local_ds_att;
|
||||
|
||||
int rc;
|
||||
@ -465,6 +466,10 @@ int Host::update_info(Template &tmpl,
|
||||
|
||||
host_share.set_ds_monitorization(local_ds_att);
|
||||
|
||||
obj_template->remove("PCI", pci_att);
|
||||
|
||||
host_share.set_pci_monitorization(pci_att);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,14 +15,330 @@
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
|
||||
#include "HostShare.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* ************************************************************************ */
|
||||
/* HostSharePCI */
|
||||
/* ************************************************************************ */
|
||||
|
||||
int HostSharePCI::from_xml_node(const xmlNodePtr node)
|
||||
{
|
||||
int rc = Template::from_xml_node(node);
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return init();
|
||||
}
|
||||
|
||||
int HostSharePCI::init()
|
||||
{
|
||||
vector<Attribute *> devices;
|
||||
|
||||
int num_devs = get("PCI", devices);
|
||||
|
||||
for (int i=0; i < num_devs; i++)
|
||||
{
|
||||
VectorAttribute * pci = dynamic_cast<VectorAttribute *>(devices[i]);
|
||||
|
||||
if (pci == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
PCIDevice * pcidev = new PCIDevice(pci);
|
||||
|
||||
pci_devices.insert(make_pair(pcidev->address, pcidev));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
bool HostSharePCI::test(unsigned int vendor_id, unsigned int device_id,
|
||||
unsigned int class_id, const VectorAttribute * devreq,
|
||||
std::set<string>& assigned) const
|
||||
{
|
||||
map<string, PCIDevice *>::const_iterator it;
|
||||
|
||||
for (it=pci_devices.begin(); it!=pci_devices.end(); it++)
|
||||
{
|
||||
PCIDevice * dev = it->second;
|
||||
|
||||
if ((class_id == 0 || dev->class_id == class_id) &&
|
||||
(vendor_id == 0 || dev->vendor_id == vendor_id) &&
|
||||
(device_id == 0 || dev->device_id == device_id) &&
|
||||
dev->vmid == -1 &&
|
||||
assigned.find(dev->address) == assigned.end())
|
||||
{
|
||||
assigned.insert(dev->address);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
bool HostSharePCI::test(vector<Attribute *> &devs) const
|
||||
{
|
||||
vector<Attribute *>::iterator it;
|
||||
std::set<string> assigned;
|
||||
|
||||
unsigned int vendor_id, device_id, class_id;
|
||||
|
||||
for ( it=devs.begin(); it!= devs.end(); it++)
|
||||
{
|
||||
VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);
|
||||
|
||||
if ( pci == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vendor_id = get_pci_value("VENDOR", pci);
|
||||
device_id = get_pci_value("DEVICE", pci);
|
||||
class_id = get_pci_value("CLASS", pci);
|
||||
|
||||
if (!test(vendor_id, device_id, class_id, pci, assigned))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
bool HostSharePCI::test_set(unsigned int vendor_id, unsigned int device_id,
|
||||
unsigned int class_id, VectorAttribute * devreq, int vmid,
|
||||
std::set<string>& assigned) const
|
||||
{
|
||||
map<string, PCIDevice *>::const_iterator it;
|
||||
|
||||
for (it=pci_devices.begin(); it!=pci_devices.end(); it++)
|
||||
{
|
||||
PCIDevice * dev = it->second;
|
||||
|
||||
if ((class_id == 0 || dev->class_id == class_id) &&
|
||||
(vendor_id == 0 || dev->vendor_id == vendor_id) &&
|
||||
(device_id == 0 || dev->device_id == device_id) &&
|
||||
dev->vmid == -1 &&
|
||||
assigned.find(dev->address) == assigned.end())
|
||||
{
|
||||
assigned.insert(dev->address);
|
||||
|
||||
if (vmid != -1)
|
||||
{
|
||||
dev->vmid = vmid;
|
||||
dev->attrs->replace("VMID", vmid);
|
||||
|
||||
devreq->replace("DOMAIN",dev->attrs->vector_value("DOMAIN"));
|
||||
devreq->replace("BUS",dev->attrs->vector_value("BUS"));
|
||||
devreq->replace("SLOT",dev->attrs->vector_value("SLOT"));
|
||||
devreq->replace("FUNCTION",dev->attrs->vector_value("FUNCTION"));
|
||||
|
||||
devreq->replace("ADDRESS",dev->attrs->vector_value("ADDRESS"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
bool HostSharePCI::test_set(vector<Attribute *> &devs, int vmid) const
|
||||
{
|
||||
vector<Attribute *>::iterator it;
|
||||
std::set<string> assigned;
|
||||
|
||||
unsigned int vendor_id, device_id, class_id;
|
||||
|
||||
for ( it=devs.begin(); it!= devs.end(); it++)
|
||||
{
|
||||
VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);
|
||||
|
||||
if ( pci == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
vendor_id = get_pci_value("VENDOR", pci);
|
||||
device_id = get_pci_value("DEVICE", pci);
|
||||
class_id = get_pci_value("CLASS", pci);
|
||||
|
||||
if (!test_set(vendor_id, device_id, class_id, pci, vmid, assigned))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
void HostSharePCI::del(const vector<Attribute *> &devs)
|
||||
{
|
||||
vector<Attribute *>::const_iterator it;
|
||||
map<string, PCIDevice *>::iterator pci_it;
|
||||
|
||||
for ( it=devs.begin(); it!= devs.end(); it++)
|
||||
{
|
||||
const VectorAttribute * pci = dynamic_cast<const VectorAttribute *>(*it);
|
||||
|
||||
if ( pci == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pci_it = pci_devices.find(pci->vector_value("ADDRESS"));
|
||||
|
||||
if (pci_it != pci_devices.end())
|
||||
{
|
||||
pci_it->second->vmid = -1;
|
||||
pci_it->second->attrs->replace("VMID",-1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
void HostSharePCI::set_monitorization(vector<Attribute*> &pci_att)
|
||||
{
|
||||
vector<Attribute*>::iterator it;
|
||||
map<string, PCIDevice*>::iterator pci_it;
|
||||
|
||||
string address;
|
||||
|
||||
for (it = pci_att.begin(); it != pci_att.end(); it++)
|
||||
{
|
||||
VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);
|
||||
|
||||
if ( pci == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
address = pci->vector_value("ADDRESS");
|
||||
|
||||
if (address.empty())
|
||||
{
|
||||
delete pci;
|
||||
continue;
|
||||
}
|
||||
|
||||
pci_it = pci_devices.find(address);
|
||||
|
||||
if (pci_it != pci_devices.end())
|
||||
{
|
||||
delete pci;
|
||||
continue;
|
||||
}
|
||||
|
||||
PCIDevice * dev = new PCIDevice(pci);
|
||||
|
||||
pci_devices.insert(make_pair(address, dev));
|
||||
|
||||
set(pci);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
unsigned int HostSharePCI::get_pci_value(const char * name,
|
||||
const VectorAttribute * pci_device)
|
||||
{
|
||||
string temp;
|
||||
|
||||
temp = pci_device->vector_value(name);
|
||||
|
||||
if (temp.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int pci_value;
|
||||
istringstream iss(temp);
|
||||
|
||||
iss >> hex >> pci_value;
|
||||
|
||||
if (iss.fail() || !iss.eof())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pci_value;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
HostSharePCI::PCIDevice::PCIDevice(VectorAttribute * _attrs)
|
||||
: vmid(-1), attrs(_attrs)
|
||||
{
|
||||
vendor_id = get_pci_value("VENDOR", attrs);
|
||||
device_id = get_pci_value("DEVICE", attrs);
|
||||
class_id = get_pci_value("CLASS", attrs);
|
||||
|
||||
if (attrs->vector_value("VMID", vmid) == -1)
|
||||
{
|
||||
attrs->replace("VMID", -1);
|
||||
}
|
||||
|
||||
attrs->vector_value("ADDRESS", address);
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------*/
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
ostream& operator<<(ostream& os, const HostSharePCI& pci)
|
||||
{
|
||||
map<string, HostSharePCI::PCIDevice *>::const_iterator it;
|
||||
|
||||
os << right << setw(15)<< "PCI ADDRESS"<< " "
|
||||
<< right << setw(8) << "CLASS" << " "
|
||||
<< right << setw(8) << "VENDOR" << " "
|
||||
<< right << setw(8) << "DEVICE" << " "
|
||||
<< right << setw(8) << "VMID" << " "
|
||||
<< endl << setw(55) << setfill('-') << "-" << setfill(' ') << endl;
|
||||
|
||||
for (it=pci.pci_devices.begin(); it!=pci.pci_devices.end(); it++)
|
||||
{
|
||||
HostSharePCI::PCIDevice * dev = it->second;
|
||||
|
||||
os << right << setw(15)<< dev->address << " "
|
||||
<< right << setw(8) << dev->class_id << " "
|
||||
<< right << setw(8) << dev->vendor_id << " "
|
||||
<< right << setw(8) << dev->device_id << " "
|
||||
<< right << setw(8) << dev->vmid << " " << endl;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
/* ************************************************************************ */
|
||||
/* HostShare :: Constructor/Destructor */
|
||||
/* ************************************************************************ */
|
||||
@ -57,7 +373,7 @@ ostream& operator<<(ostream& os, HostShare& hs)
|
||||
|
||||
string& HostShare::to_xml(string& xml) const
|
||||
{
|
||||
string template_xml;
|
||||
string ds_xml, pci_xml;
|
||||
ostringstream oss;
|
||||
|
||||
oss << "<HOST_SHARE>"
|
||||
@ -74,7 +390,8 @@ string& HostShare::to_xml(string& xml) const
|
||||
<< "<USED_MEM>" << used_mem << "</USED_MEM>"
|
||||
<< "<USED_CPU>" << used_cpu << "</USED_CPU>"
|
||||
<< "<RUNNING_VMS>"<<running_vms <<"</RUNNING_VMS>"
|
||||
<< ds_template.to_xml(template_xml)
|
||||
<< ds.to_xml(ds_xml)
|
||||
<< pci.to_xml(pci_xml)
|
||||
<< "</HOST_SHARE>";
|
||||
|
||||
xml = oss.str();
|
||||
@ -111,7 +428,7 @@ int HostShare::from_xml_node(const xmlNodePtr node)
|
||||
|
||||
rc += xpath(running_vms,"/HOST_SHARE/RUNNING_VMS",-1);
|
||||
|
||||
// ------------ DS Template ---------------
|
||||
// ------------ Datastores ---------------
|
||||
|
||||
ObjectXML::get_nodes("/HOST_SHARE/DATASTORES", content);
|
||||
|
||||
@ -120,7 +437,27 @@ int HostShare::from_xml_node(const xmlNodePtr node)
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc += ds_template.from_xml_node( content[0] );
|
||||
rc += ds.from_xml_node( content[0] );
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
|
||||
content.clear();
|
||||
|
||||
if (rc != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------ PCI Devices ---------------
|
||||
|
||||
ObjectXML::get_nodes("/HOST_SHARE/PCI_DEVICES", content);
|
||||
|
||||
if( content.empty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc += pci.from_xml_node( content[0] );
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
|
||||
@ -134,14 +471,22 @@ int HostShare::from_xml_node(const xmlNodePtr node)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void HostShare::set_ds_monitorization(const vector<Attribute*> &ds_att)
|
||||
{
|
||||
vector<Attribute*>::const_iterator it;
|
||||
|
||||
ds_template.erase("DS");
|
||||
ds.erase("DS");
|
||||
|
||||
for (it = ds_att.begin(); it != ds_att.end(); it++)
|
||||
{
|
||||
ds_template.set(*it);
|
||||
ds.set(*it);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
@ -69,6 +69,52 @@ class DummyInformationManager < OpenNebulaDriver
|
||||
results << "DS_LOCATION_TOTAL_MB=20480\n"
|
||||
results << "DS_LOCATION_FREE_MB=20480\n"
|
||||
|
||||
results << "PCI = [
|
||||
ADDRESS = \"0000:02:00:0\",\n
|
||||
BUS = \"02\",\n
|
||||
CLASS = \"0300\",\n
|
||||
CLASS_NAME = \"VGA compatible controller\",\n
|
||||
DEVICE = \"0863\",\n
|
||||
DEVICE_NAME = \"C79 [GeForce 9400M]\",\n
|
||||
DOMAIN = \"0000\",\n
|
||||
FUNCTION = \"0\",\n
|
||||
SHORT_ADDRESS = \"02:00.0\",\n
|
||||
SLOT = \"00\",\n
|
||||
TYPE = \"10de:0863:0300\",\n
|
||||
VENDOR = \"10de\",\n
|
||||
VENDOR_NAME = \"NVIDIA Corporation\"\n
|
||||
]\n
|
||||
PCI = [
|
||||
ADDRESS = \"0000:00:06:0\",\n
|
||||
BUS = \"00\",\n
|
||||
CLASS = \"0c03\",\n
|
||||
CLASS_NAME = \"USB controller\",\n
|
||||
DEVICE = \"0aa7\",\n
|
||||
DEVICE_NAME = \"MCP79 OHCI USB 1.1 Controller\",\n
|
||||
DOMAIN = \"0000\",\n
|
||||
FUNCTION = \"0\",\n
|
||||
SHORT_ADDRESS = \"00:06.0\",\n
|
||||
SLOT = \"06\",\n
|
||||
TYPE = \"10de:0aa7:0c03\",\n
|
||||
VENDOR = \"10de\",\n
|
||||
VENDOR_NAME = \"NVIDIA Corporation\"\n
|
||||
]\n
|
||||
PCI = [
|
||||
ADDRESS = \"0000:00:06:1\",\n
|
||||
BUS = \"00\",\n
|
||||
CLASS = \"0c03\",\n
|
||||
CLASS_NAME = \"USB controller\",\n
|
||||
DEVICE = \"0aa9\",\n
|
||||
DEVICE_NAME = \"MCP79 EHCI USB 2.0 Controller\",\n
|
||||
DOMAIN = \"0000\",\n
|
||||
FUNCTION = \"1\",\n
|
||||
SHORT_ADDRESS = \"00:06.1\",\n
|
||||
SLOT = \"06\",\n
|
||||
TYPE = \"10de:0aa9:0c03\",\n
|
||||
VENDOR = \"10de\",\n
|
||||
VENDOR_NAME = \"NVIDIA Corporation\"\n
|
||||
]\n"
|
||||
|
||||
results = Base64::encode64(results).strip.delete("\n")
|
||||
|
||||
send_message("MONITOR", RESULT[:success], number, results)
|
||||
|
114
src/im_mad/remotes/kvm-probes.d/pci.rb
Executable file
114
src/im_mad/remotes/kvm-probes.d/pci.rb
Executable file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# -------------------------------------------------------------------------- #
|
||||
# Copyright 2002-2015, 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. #
|
||||
#--------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
# This variable contains the filters for PCI card monitoring. The format
|
||||
# is the same as lspci and several filters can be added separated by commas.
|
||||
# A nil filter will retrieve all PCI cards.
|
||||
#
|
||||
# From lspci help:
|
||||
# -d [<vendor>]:[<device>][:<class>]
|
||||
#
|
||||
# For example
|
||||
#
|
||||
# FILTER = '::0300' # all VGA cards
|
||||
# FILTER = '10de::0300' # all NVIDIA VGA cards
|
||||
# FILTER = '10de:11bf:0300' # only GK104GL [GRID K2]
|
||||
# FILTER = '8086::0300,::0106' # all Intel VGA cards and any SATA controller
|
||||
|
||||
FILTER = nil
|
||||
|
||||
require 'shellwords'
|
||||
|
||||
def get_pci(filter=nil)
|
||||
command = "lspci -mmnn"
|
||||
command << " -d #{filter}" if filter
|
||||
|
||||
text = %x(#{command})
|
||||
|
||||
text.split("\n").map {|l| Shellwords.split(l) }
|
||||
end
|
||||
|
||||
def get_name_and_id(text)
|
||||
m = text.match(/^(.*) \[(....)\]$/)
|
||||
return m[1], m[2]
|
||||
end
|
||||
|
||||
def parse_pci(pci)
|
||||
card = {}
|
||||
|
||||
card[:short_address] = pci[0]
|
||||
card[:libvirt_address] =
|
||||
"pci_0000_#{card[:short_address].gsub(/[:.]/, '_')}"
|
||||
card[:address] = "0000:#{card[:short_address].gsub(/[:.]/, ':')}"
|
||||
|
||||
card[:class_name], card[:class] = get_name_and_id(pci[1])
|
||||
card[:vendor_name], card[:vendor] = get_name_and_id(pci[2])
|
||||
card[:device_name], card[:device] = get_name_and_id(pci[3])
|
||||
|
||||
card[:bus], card[:slot], card[:function] = pci[0].split(/[:.]/)
|
||||
|
||||
card[:type] = [card[:vendor], card[:device], card[:class]].join(':')
|
||||
|
||||
card
|
||||
end
|
||||
|
||||
def get_devices(filter=nil)
|
||||
if filter
|
||||
filter = filter.split(',')
|
||||
else
|
||||
filter = [nil]
|
||||
end
|
||||
|
||||
filter.map do |f|
|
||||
get_pci(f).map {|pci| parse_pci(pci) }
|
||||
end.flatten
|
||||
end
|
||||
|
||||
filter = FILTER
|
||||
|
||||
devices = get_devices(filter)
|
||||
|
||||
def pval(name, value)
|
||||
%Q( #{name} = "#{value}")
|
||||
end
|
||||
|
||||
devices.each do |dev|
|
||||
puts "PCI = ["
|
||||
values = [
|
||||
pval('TYPE', dev[:type]),
|
||||
pval('VENDOR', dev[:vendor]),
|
||||
pval('VENDOR_NAME', dev[:vendor_name]),
|
||||
pval('DEVICE', dev[:device]),
|
||||
pval('DEVICE_NAME', dev[:device_name]),
|
||||
pval('CLASS', dev[:class]),
|
||||
pval('CLASS_NAME', dev[:class_name]),
|
||||
pval('ADDRESS', dev[:address]),
|
||||
pval('SHORT_ADDRESS', dev[:short_address]),
|
||||
pval('DOMAIN', '0000'),
|
||||
pval('BUS', dev[:bus]),
|
||||
pval('SLOT', dev[:slot]),
|
||||
pval('FUNCTION', dev[:function])
|
||||
]
|
||||
|
||||
puts values.join(",\n")
|
||||
puts "]"
|
||||
end
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@ void LifeCycleManager::deploy_action(int vid)
|
||||
{
|
||||
time_t thetime = time(0);
|
||||
int cpu,mem,disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
VirtualMachine::LcmState vm_state;
|
||||
TransferManager::Actions tm_action;
|
||||
@ -43,7 +44,7 @@ void LifeCycleManager::deploy_action(int vid)
|
||||
// PROLOG STATE
|
||||
//----------------------------------------------------
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
vm_state = VirtualMachine::PROLOG;
|
||||
tm_action = TransferManager::PROLOG;
|
||||
@ -75,7 +76,7 @@ void LifeCycleManager::deploy_action(int vid)
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
if (hpool->add_capacity(vm->get_hid(),vm->get_oid(),cpu,mem,disk) == -1)
|
||||
if (hpool->add_capacity(vm->get_hid(),vm->get_oid(),cpu,mem,disk,pci) == -1)
|
||||
{
|
||||
//The host has been deleted, move VM to FAILURE
|
||||
this->trigger(LifeCycleManager::PROLOG_FAILURE, vid);
|
||||
@ -211,6 +212,8 @@ void LifeCycleManager::migrate_action(int vid)
|
||||
VirtualMachine * vm;
|
||||
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
vm = vmpool->get(vid,true);
|
||||
@ -239,9 +242,9 @@ void LifeCycleManager::migrate_action(int vid)
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
@ -278,11 +281,12 @@ void LifeCycleManager::migrate_action(int vid)
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem,
|
||||
disk, pci);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
@ -321,11 +325,12 @@ void LifeCycleManager::migrate_action(int vid)
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem,
|
||||
disk, pci);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
@ -359,7 +364,8 @@ void LifeCycleManager::live_migrate_action(int vid)
|
||||
if (vm->get_state() == VirtualMachine::ACTIVE &&
|
||||
vm->get_lcm_state() == VirtualMachine::RUNNING)
|
||||
{
|
||||
int cpu,mem,disk;
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
//----------------------------------------------------
|
||||
// MIGRATE STATE
|
||||
@ -377,9 +383,9 @@ void LifeCycleManager::live_migrate_action(int vid)
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->add_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
@ -845,6 +851,7 @@ void LifeCycleManager::clean_action(int vid)
|
||||
void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& image_id)
|
||||
{
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
time_t the_time = time(0);
|
||||
|
||||
VirtualMachine::LcmState state = vm->get_lcm_state();
|
||||
@ -873,8 +880,8 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag
|
||||
vm->set_vm_info();
|
||||
vm->set_reason(History::USER);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
@ -1005,7 +1012,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag
|
||||
vmpool->update_previous_history(vm);
|
||||
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu,
|
||||
mem, disk);
|
||||
mem, disk, pci);
|
||||
|
||||
vmm->trigger(VirtualMachineManager::DRIVER_CANCEL,vid);
|
||||
vmm->trigger(VirtualMachineManager::CLEANUP_BOTH,vid);
|
||||
@ -1031,7 +1038,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag
|
||||
vmpool->update_previous_history(vm);
|
||||
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu,
|
||||
mem, disk);
|
||||
mem, disk, pci);
|
||||
|
||||
vmm->trigger(VirtualMachineManager::DRIVER_CANCEL,vid);
|
||||
vmm->trigger(VirtualMachineManager::CLEANUP_PREVIOUS,vid);
|
||||
|
@ -37,8 +37,10 @@ void LifeCycleManager::save_success_action(int vid)
|
||||
|
||||
if ( vm->get_lcm_state() == VirtualMachine::SAVE_MIGRATE )
|
||||
{
|
||||
int cpu,mem,disk;
|
||||
time_t the_time = time(0);
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
//----------------------------------------------------
|
||||
// PROLOG_MIGRATE STATE
|
||||
@ -66,9 +68,9 @@ void LifeCycleManager::save_success_action(int vid)
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->del_capacity(vm->get_previous_hid(),vm->get_oid(),cpu,mem,disk,pci);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
@ -154,8 +156,10 @@ void LifeCycleManager::save_failure_action(int vid)
|
||||
|
||||
if ( vm->get_lcm_state() == VirtualMachine::SAVE_MIGRATE )
|
||||
{
|
||||
int cpu,mem,disk;
|
||||
time_t the_time = time(0);
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
//----------------------------------------------------
|
||||
// RUNNING STATE FROM SAVE_MIGRATE
|
||||
@ -171,9 +175,9 @@ void LifeCycleManager::save_failure_action(int vid)
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
vm->set_previous_etime(the_time);
|
||||
|
||||
@ -256,8 +260,10 @@ void LifeCycleManager::deploy_success_action(int vid)
|
||||
|
||||
if ( vm->get_lcm_state() == VirtualMachine::MIGRATE )
|
||||
{
|
||||
int cpu,mem,disk;
|
||||
time_t the_time = time(0);
|
||||
int cpu,mem,disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
vm->set_running_stime(the_time);
|
||||
|
||||
@ -275,9 +281,9 @@ void LifeCycleManager::deploy_success_action(int vid)
|
||||
|
||||
vmpool->update_previous_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->del_capacity(vm->get_previous_hid(),vm->get_oid(),cpu,mem,disk,pci);
|
||||
|
||||
vm->set_state(VirtualMachine::RUNNING);
|
||||
|
||||
@ -328,8 +334,10 @@ void LifeCycleManager::deploy_failure_action(int vid)
|
||||
|
||||
if ( vm->get_lcm_state() == VirtualMachine::MIGRATE )
|
||||
{
|
||||
int cpu,mem,disk;
|
||||
time_t the_time = time(0);
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
time_t the_time = time(0);
|
||||
|
||||
//----------------------------------------------------
|
||||
// RUNNING STATE FROM MIGRATE
|
||||
@ -357,9 +365,9 @@ void LifeCycleManager::deploy_failure_action(int vid)
|
||||
|
||||
vmpool->update_previous_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
// --- Add new record by copying the previous one
|
||||
|
||||
@ -789,8 +797,10 @@ void LifeCycleManager::prolog_failure_action(int vid)
|
||||
void LifeCycleManager::epilog_success_action(int vid)
|
||||
{
|
||||
VirtualMachine * vm;
|
||||
time_t the_time = time(0);
|
||||
int cpu,mem,disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
time_t the_time = time(0);
|
||||
int cpu,mem,disk;
|
||||
|
||||
VirtualMachine::LcmState state;
|
||||
DispatchManager::Actions action;
|
||||
@ -859,9 +869,9 @@ void LifeCycleManager::epilog_success_action(int vid)
|
||||
|
||||
vmpool->update_history(vm);
|
||||
|
||||
vm->get_requirements(cpu,mem,disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk);
|
||||
hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk, pci);
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
|
@ -938,7 +938,7 @@ EOT
|
||||
# Calculate the host's xml and write them to host_pool_new
|
||||
@db.transaction do
|
||||
@db[:host_pool].each do |row|
|
||||
host_doc = Document.new(row[:body])
|
||||
host_doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
|
||||
|
||||
hid = row[:oid]
|
||||
|
||||
@ -949,54 +949,67 @@ EOT
|
||||
mem_usage = counters_host[:memory]*1024
|
||||
|
||||
# rewrite running_vms
|
||||
host_doc.root.each_element("HOST_SHARE/RUNNING_VMS") {|e|
|
||||
host_doc.root.xpath("HOST_SHARE/RUNNING_VMS").each {|e|
|
||||
if e.text != rvms.to_s
|
||||
log_error(
|
||||
"Host #{hid} RUNNING_VMS has #{e.text} \tis\t#{rvms}")
|
||||
e.text = rvms
|
||||
e.content = rvms
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
# re-do list of VM IDs
|
||||
vms_elem = host_doc.root.elements.delete("VMS")
|
||||
vms_elem = host_doc.root.at_xpath("VMS").remove
|
||||
|
||||
vms_new_elem = host_doc.root.add_element("VMS")
|
||||
vms_new_elem = host_doc.create_element("VMS")
|
||||
host_doc.root.add_child(vms_new_elem)
|
||||
|
||||
counters_host[:rvms].each do |id|
|
||||
id_elem = vms_elem.elements.delete("ID[.=#{id}]")
|
||||
id_elem = vms_elem.at_xpath("ID[.=#{id}]")
|
||||
|
||||
if id_elem.nil?
|
||||
log_error(
|
||||
"VM #{id} is missing from Host #{hid} VM id list")
|
||||
else
|
||||
id_elem.remove
|
||||
end
|
||||
|
||||
vms_new_elem.add_element("ID").text = id.to_s
|
||||
vms_new_elem.add_child(host_doc.create_element("ID")).content = id.to_s
|
||||
end
|
||||
|
||||
vms_elem.each_element("ID") do |id_elem|
|
||||
vms_elem.xpath("ID").each do |id_elem|
|
||||
log_error(
|
||||
"VM #{id_elem.text} is in Host #{hid} VM id list, "<<
|
||||
"but it should not")
|
||||
end
|
||||
|
||||
host_doc.root.xpath("HOST_SHARE/PCI_DEVICES/PCI").each do |pci|
|
||||
if !pci.at_xpath("VMID").nil?
|
||||
vmid = pci.at_xpath("VMID").text.to_i
|
||||
|
||||
if vmid != -1 && !counters_host[:rvms].include?(vmid)
|
||||
log_error("VM #{vmid} has a PCI device assigned in host #{hid}, but it should not. Device: #{pci.at_xpath('DEVICE_NAME').text}")
|
||||
pci.at_xpath("VMID").content = "-1"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# rewrite cpu
|
||||
host_doc.root.each_element("HOST_SHARE/CPU_USAGE") {|e|
|
||||
host_doc.root.xpath("HOST_SHARE/CPU_USAGE").each {|e|
|
||||
if e.text != cpu_usage.to_s
|
||||
log_error(
|
||||
"Host #{hid} CPU_USAGE has #{e.text} "<<
|
||||
"\tis\t#{cpu_usage}")
|
||||
e.text = cpu_usage
|
||||
e.content = cpu_usage
|
||||
end
|
||||
}
|
||||
|
||||
# rewrite memory
|
||||
host_doc.root.each_element("HOST_SHARE/MEM_USAGE") {|e|
|
||||
host_doc.root.xpath("HOST_SHARE/MEM_USAGE").each {|e|
|
||||
if e.text != mem_usage.to_s
|
||||
log_error("Host #{hid} MEM_USAGE has #{e.text} "<<
|
||||
"\tis\t#{mem_usage}")
|
||||
e.text = mem_usage
|
||||
e.content = mem_usage
|
||||
end
|
||||
}
|
||||
|
||||
|
@ -113,6 +113,34 @@ module Migrator
|
||||
|
||||
log_time()
|
||||
|
||||
@db.run "ALTER TABLE host_pool RENAME TO old_host_pool;"
|
||||
@db.run "CREATE TABLE host_pool (oid INTEGER PRIMARY KEY, name VARCHAR(128), body MEDIUMTEXT, state INTEGER, last_mon_time INTEGER, uid INTEGER, gid INTEGER, owner_u INTEGER, group_u INTEGER, other_u INTEGER, cid INTEGER, UNIQUE(name));"
|
||||
|
||||
@db.transaction do
|
||||
@db.fetch("SELECT * FROM old_host_pool") do |row|
|
||||
doc = Nokogiri::XML(row[:body],nil,NOKOGIRI_ENCODING){|c| c.default_xml.noblanks}
|
||||
|
||||
doc.root.at_xpath("HOST_SHARE").add_child(doc.create_element("PCI_DEVICES"))
|
||||
|
||||
@db[:host_pool].insert(
|
||||
:oid => row[:oid],
|
||||
:name => row[:name],
|
||||
:body => doc.root.to_s,
|
||||
:state => row[:state],
|
||||
:last_mon_time => row[:last_mon_time],
|
||||
:uid => row[:uid],
|
||||
:gid => row[:gid],
|
||||
:owner_u => row[:owner_u],
|
||||
:group_u => row[:group_u],
|
||||
:other_u => row[:other_u],
|
||||
:cid => row[:cid])
|
||||
end
|
||||
end
|
||||
|
||||
@db.run "DROP TABLE old_host_pool;"
|
||||
|
||||
log_time()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -375,17 +375,20 @@ int RequestManagerVirtualMachine::get_host_information(
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool RequestManagerVirtualMachine::check_host(int hid,
|
||||
int cpu,
|
||||
int mem,
|
||||
int disk,
|
||||
string& error)
|
||||
bool RequestManagerVirtualMachine::check_host(
|
||||
int hid, bool enforce, VirtualMachine* vm, string& error)
|
||||
{
|
||||
Nebula& nd = Nebula::instance();
|
||||
HostPool * hpool = nd.get_hpool();
|
||||
|
||||
Host * host;
|
||||
bool test;
|
||||
string capacity_error;
|
||||
|
||||
int cpu, mem, disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
host = hpool->get(hid, true);
|
||||
|
||||
@ -395,14 +398,22 @@ bool RequestManagerVirtualMachine::check_host(int hid,
|
||||
return false;
|
||||
}
|
||||
|
||||
test = host->test_capacity(cpu, mem, disk);
|
||||
if (!enforce)
|
||||
{
|
||||
cpu = 0;
|
||||
mem = 0;
|
||||
disk = 0;
|
||||
}
|
||||
|
||||
test = host->test_capacity(cpu, mem, disk, pci, capacity_error);
|
||||
|
||||
if (!test)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << object_name(PoolObjectSQL::HOST)
|
||||
<< " " << hid << " does not have enough capacity.";
|
||||
oss << object_name(PoolObjectSQL::VM) << " [" << vm->get_oid()
|
||||
<< "] does not fit in " << object_name(PoolObjectSQL::HOST)
|
||||
<< " [" << hid << "]. " << capacity_error;
|
||||
|
||||
error = oss.str();
|
||||
}
|
||||
@ -662,6 +673,8 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
|
||||
bool auth = false;
|
||||
|
||||
string error;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Get request parameters and information about the target host
|
||||
// ------------------------------------------------------------------------
|
||||
@ -814,25 +827,12 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
return;
|
||||
}
|
||||
|
||||
if (enforce)
|
||||
if (check_host(hid, enforce, vm, error) == false)
|
||||
{
|
||||
int cpu, mem, disk;
|
||||
string error;
|
||||
|
||||
vm->get_requirements(cpu, mem, disk);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
if (check_host(hid, cpu, mem, disk, error) == false)
|
||||
{
|
||||
failure_response(ACTION, request_error(error,""), att);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((vm = get_vm(id, att)) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
failure_response(ACTION, request_error(error,""), att);
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -897,6 +897,8 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
|
||||
|
||||
bool auth = false;
|
||||
|
||||
string error;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Get request parameters and information about the target host
|
||||
// ------------------------------------------------------------------------
|
||||
@ -1031,26 +1033,16 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList
|
||||
}
|
||||
|
||||
// Check the host has enough capacity
|
||||
if (enforce)
|
||||
{
|
||||
int cpu, mem, disk;
|
||||
string error;
|
||||
|
||||
vm->get_requirements(cpu, mem, disk);
|
||||
|
||||
vm->unlock();
|
||||
|
||||
if (check_host(hid, cpu, mem, disk, error) == false)
|
||||
{
|
||||
failure_response(ACTION, request_error(error,""), att);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (check_host(hid, enforce, vm, error) == false)
|
||||
{
|
||||
vm->unlock();
|
||||
|
||||
failure_response(ACTION, request_error(error,""), att);
|
||||
return;
|
||||
}
|
||||
|
||||
vm->unlock();
|
||||
|
||||
// Check we are in the same cluster
|
||||
Host * host = nd.get_hpool()->get(c_hid, true);
|
||||
|
||||
@ -1831,6 +1823,9 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
int dcpu_host = (int) (dcpu * 100);//now in 100%
|
||||
int dmem_host = dmemory * 1024; //now in Kilobytes
|
||||
|
||||
vector<Attribute *> empty_pci;
|
||||
string error;
|
||||
|
||||
host = hpool->get(hid, true);
|
||||
|
||||
if (host == 0)
|
||||
@ -1844,7 +1839,7 @@ void VirtualMachineResize::request_execute(xmlrpc_c::paramList const& paramList,
|
||||
return;
|
||||
}
|
||||
|
||||
if ( enforce && host->test_capacity(dcpu_host, dmem_host, 0) == false)
|
||||
if ( enforce && host->test_capacity(dcpu_host, dmem_host, 0, empty_pci, error) == false)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <map>
|
||||
#include "ObjectXML.h"
|
||||
#include "HostShare.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -50,21 +51,24 @@ public:
|
||||
* Tests whether a new VM can be hosted by the host or not
|
||||
* @param cpu needed by the VM (percentage)
|
||||
* @param mem needed by the VM (in KB)
|
||||
* @param pci devices needed by the VM
|
||||
* @param error error message
|
||||
* @return true if the share can host the VM
|
||||
*/
|
||||
bool test_capacity(long long cpu, long long mem, string & error) const;
|
||||
bool test_capacity(long long cpu, long long mem, vector<Attribute *> &pci,
|
||||
string & error);
|
||||
|
||||
/**
|
||||
* Tests whether a new VM can be hosted by the host or not
|
||||
* @param cpu needed by the VM (percentage)
|
||||
* @param mem needed by the VM (in KB)
|
||||
* @param pci devices needed by the VM
|
||||
* @return true if the share can host the VM
|
||||
*/
|
||||
bool test_capacity(long long cpu, long long mem) const
|
||||
bool test_capacity(long long cpu,long long mem,vector<Attribute *> &p)
|
||||
{
|
||||
string tmp_st;
|
||||
return test_capacity(cpu, mem, tmp_st);
|
||||
return test_capacity(cpu, mem, p, tmp_st);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -74,11 +78,14 @@ public:
|
||||
* @param mem needed by the VM (in KB)
|
||||
* @return 0 on success
|
||||
*/
|
||||
void add_capacity(long long cpu, long long mem)
|
||||
void add_capacity(int vmid, long long cpu, long long mem,
|
||||
vector<Attribute *> &p)
|
||||
{
|
||||
cpu_usage += cpu;
|
||||
mem_usage += mem;
|
||||
|
||||
pci.add(p, vmid);
|
||||
|
||||
running_vms++;
|
||||
};
|
||||
|
||||
@ -131,6 +138,12 @@ public:
|
||||
return public_cloud;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the Host information to an output stream. This function is used
|
||||
* for logging purposes.
|
||||
*/
|
||||
friend ostream& operator<<(ostream& o, const HostXML& p);
|
||||
|
||||
private:
|
||||
int oid;
|
||||
int cluster_id;
|
||||
@ -150,6 +163,8 @@ private:
|
||||
|
||||
bool public_cloud;
|
||||
|
||||
HostSharePCI pci;
|
||||
|
||||
// Configuration attributes
|
||||
static const char *host_paths[]; /**< paths for search function */
|
||||
|
||||
|
@ -116,7 +116,8 @@ public:
|
||||
return ds_requirements;
|
||||
}
|
||||
|
||||
void get_requirements (int& cpu, int& memory, long long& disk);
|
||||
void get_requirements (int& cpu, int& memory, long long& disk,
|
||||
vector<Attribute *> &pci);
|
||||
|
||||
map<int,long long> get_storage_usage();
|
||||
|
||||
|
@ -29,11 +29,13 @@ int HostPoolXML::set_up()
|
||||
{
|
||||
oss << "Discovered Hosts (enabled):" << endl;
|
||||
|
||||
map<int,ObjectXML*>::iterator it;
|
||||
map<int, ObjectXML*>::iterator it;
|
||||
|
||||
for (it=objects.begin();it!=objects.end();it++)
|
||||
{
|
||||
oss << " " << it->first;
|
||||
HostXML * h = dynamic_cast<HostXML *>(it->second);
|
||||
|
||||
oss << *h << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
|
||||
#include "HostXML.h"
|
||||
#include "NebulaUtil.h"
|
||||
@ -36,36 +38,50 @@ const char *HostXML::host_paths[] = {
|
||||
|
||||
void HostXML::init_attributes()
|
||||
{
|
||||
xpath(oid, "/HOST/ID", -1);
|
||||
xpath(cluster_id, "/HOST/CLUSTER_ID", -1);
|
||||
xpath(mem_usage, "/HOST/HOST_SHARE/MEM_USAGE", 0);
|
||||
xpath(cpu_usage, "/HOST/HOST_SHARE/CPU_USAGE", 0);
|
||||
xpath(max_mem, "/HOST/HOST_SHARE/MAX_MEM", 0);
|
||||
xpath(max_cpu, "/HOST/HOST_SHARE/MAX_CPU", 0);
|
||||
xpath(free_disk, "/HOST/HOST_SHARE/FREE_DISK", 0);
|
||||
xpath(running_vms, "/HOST/HOST_SHARE/RUNNING_VMS", 0);
|
||||
xpath(oid, "/HOST/ID", -1);
|
||||
xpath(cluster_id, "/HOST/CLUSTER_ID", -1);
|
||||
xpath(mem_usage, "/HOST/HOST_SHARE/MEM_USAGE", 0);
|
||||
xpath(cpu_usage, "/HOST/HOST_SHARE/CPU_USAGE", 0);
|
||||
xpath(max_mem, "/HOST/HOST_SHARE/MAX_MEM", 0);
|
||||
xpath(max_cpu, "/HOST/HOST_SHARE/MAX_CPU", 0);
|
||||
xpath(free_disk, "/HOST/HOST_SHARE/FREE_DISK", 0);
|
||||
xpath(running_vms, "/HOST/HOST_SHARE/RUNNING_VMS", 0);
|
||||
|
||||
string public_cloud_st;
|
||||
|
||||
xpath(public_cloud_st, "/HOST/TEMPLATE/PUBLIC_CLOUD", "");
|
||||
public_cloud = (one_util::toupper(public_cloud_st) == "YES");
|
||||
|
||||
vector<string> ds_ids = (*this)["/HOST/HOST_SHARE/DATASTORES/DS/ID"];
|
||||
vector<string> ds_free_mb = (*this)["/HOST/HOST_SHARE/DATASTORES/DS/FREE_MB"];
|
||||
//-------------------- HostShare Datastores ------------------------------
|
||||
vector<string> ds_ids = (*this)["/HOST/HOST_SHARE/DATASTORES/DS/ID"];
|
||||
vector<string> ds_free = (*this)["/HOST/HOST_SHARE/DATASTORES/DS/FREE_MB"];
|
||||
|
||||
int id;
|
||||
long long disk;
|
||||
|
||||
for (size_t i = 0; i < ds_ids.size() && i < ds_free_mb.size(); i++)
|
||||
for (size_t i = 0; i < ds_ids.size() && i < ds_free.size(); i++)
|
||||
{
|
||||
id = atoi(ds_ids[i].c_str());
|
||||
disk = atoll(ds_free_mb[i].c_str());
|
||||
disk = atoll(ds_free[i].c_str());
|
||||
|
||||
ds_free_disk[id] = disk;
|
||||
}
|
||||
|
||||
//Init search xpath routes
|
||||
//-------------------- HostShare PCI Devices ------------------------------
|
||||
vector<xmlNodePtr> content;
|
||||
|
||||
get_nodes("/HOST/HOST_SHARE/PCI_DEVICES", content);
|
||||
|
||||
if( !content.empty())
|
||||
{
|
||||
pci.from_xml_node(content[0]);
|
||||
|
||||
free_nodes(content);
|
||||
|
||||
content.clear();
|
||||
}
|
||||
|
||||
//-------------------- Init search xpath routes ---------------------------
|
||||
ObjectXML::paths = host_paths;
|
||||
ObjectXML::num_paths = host_num_paths;
|
||||
}
|
||||
@ -111,30 +127,46 @@ int HostXML::search(const char *name, int& value)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
bool HostXML::test_capacity(long long cpu, long long mem, string & error) const
|
||||
bool HostXML::test_capacity(long long cpu, long long mem,
|
||||
vector<Attribute *>& p, string & error)
|
||||
{
|
||||
bool fits = (((max_cpu - cpu_usage ) >= cpu) &&
|
||||
((max_mem - mem_usage ) >= mem));
|
||||
|
||||
bool pci_fits = pci.test(p);
|
||||
bool fits = ((max_cpu - cpu_usage ) >= cpu) &&
|
||||
((max_mem - mem_usage ) >= mem) &&
|
||||
pci_fits;
|
||||
if (!fits)
|
||||
{
|
||||
if (NebulaLog::log_level() >= Log::DDEBUG)
|
||||
{
|
||||
ostringstream oss;
|
||||
if ( pci_fits )
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
oss << "Not enough capacity. "
|
||||
<< "Requested: "
|
||||
<< cpu << " CPU, "
|
||||
<< mem << " KB MEM; "
|
||||
<< "Available: "
|
||||
<< (max_cpu - cpu_usage ) << " CPU, "
|
||||
<< (max_mem - mem_usage ) << " KB MEM";
|
||||
oss << "Not enough capacity. "
|
||||
<< "Requested: "
|
||||
<< cpu << " CPU, "
|
||||
<< mem << " KB MEM; "
|
||||
<< "Available: "
|
||||
<< (max_cpu - cpu_usage ) << " CPU, "
|
||||
<< (max_mem - mem_usage ) << " KB MEM";
|
||||
|
||||
error = oss.str();
|
||||
error = oss.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Unavailable PCI device.";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Not enough capacity.";
|
||||
if ( pci_fits )
|
||||
{
|
||||
error = "Not enough capacity.";
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "Unavailable PCI device.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,3 +201,33 @@ void HostXML::add_ds_capacity(int dsid, long long vm_disk_mb)
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
ostream& operator<<(ostream& o, const HostXML& p)
|
||||
{
|
||||
map<int, long long>::const_iterator it;
|
||||
|
||||
o << "ID : " << p.oid << endl;
|
||||
o << "CLUSTER_ID : " << p.cluster_id << endl;
|
||||
o << "MEM_USAGE : " << p.mem_usage << endl;
|
||||
o << "CPU_USAGE : " << p.cpu_usage << endl;
|
||||
o << "MAX_MEM : " << p.max_mem << endl;
|
||||
o << "MAX_CPU : " << p.max_cpu << endl;
|
||||
o << "FREE_DISK : " << p.free_disk << endl;
|
||||
o << "RUNNING_VMS : " << p.running_vms << endl;
|
||||
o << "PUBLIC : " << p.public_cloud << endl;
|
||||
|
||||
o << endl
|
||||
<< right << setw(5) << "DSID" << " "
|
||||
<< right << setw(15) << "FREE_MB" << " "
|
||||
<< endl << setw(30) << setfill('-') << "-" << setfill (' ') << endl;
|
||||
|
||||
for (it = p.ds_free_disk.begin() ; it != p.ds_free_disk.end() ; it++)
|
||||
{
|
||||
o << right << setw(5) << it->first << " "
|
||||
<< right << setw(15)<< it->second<< " " << endl;
|
||||
}
|
||||
|
||||
o << endl << p.pci;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ int VirtualMachinePoolXML::set_up()
|
||||
<< right << setw(8) << "VM" << " "
|
||||
<< right << setw(4) << "CPU" << " "
|
||||
<< right << setw(11) << "Memory" << " "
|
||||
<< right << setw(3) << "PCI" << " "
|
||||
<< right << setw(11) << "System DS" << " "
|
||||
<< " Image DS"
|
||||
<< endl << setw(60) << setfill('-') << "-" << setfill(' ');
|
||||
@ -47,11 +48,13 @@ int VirtualMachinePoolXML::set_up()
|
||||
{
|
||||
int cpu, mem;
|
||||
long long disk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
string action = "DEPLOY";
|
||||
|
||||
VirtualMachineXML * vm = static_cast<VirtualMachineXML *>(it->second);
|
||||
|
||||
vm->get_requirements(cpu, mem, disk);
|
||||
vm->get_requirements(cpu, mem, disk, pci);
|
||||
|
||||
if (vm->is_resched())
|
||||
{
|
||||
@ -67,6 +70,7 @@ int VirtualMachinePoolXML::set_up()
|
||||
<< right << setw(8) << it->first << " "
|
||||
<< right << setw(4) << cpu << " "
|
||||
<< right << setw(11) << mem << " "
|
||||
<< right << setw(3) << pci.size() << " "
|
||||
<< right << setw(11) << disk << " ";
|
||||
|
||||
map<int,long long> ds_usage = vm->get_storage_usage();
|
||||
|
@ -202,8 +202,16 @@ ostream& operator<<(ostream& os, VirtualMachineXML& vm)
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachineXML::get_requirements (int& cpu, int& memory, long long& disk)
|
||||
void VirtualMachineXML::get_requirements (int& cpu, int& memory,
|
||||
long long& disk, vector<Attribute *> &pci)
|
||||
{
|
||||
pci.clear();
|
||||
|
||||
if (vm_template != 0)
|
||||
{
|
||||
vm_template->get("PCI", pci);
|
||||
}
|
||||
|
||||
if (this->memory == 0 || this->cpu == 0)
|
||||
{
|
||||
cpu = 0;
|
||||
|
@ -39,6 +39,7 @@ sched_env.Prepend(LIBS=[
|
||||
'nebula_core',
|
||||
'nebula_template',
|
||||
'nebula_vm',
|
||||
'nebula_host',
|
||||
'crypto',
|
||||
'xml2'
|
||||
])
|
||||
|
@ -502,6 +502,7 @@ int Scheduler::set_up_pools()
|
||||
* @param vm the virtual machine
|
||||
* @param vm_memory vm requirement
|
||||
* @param vm_cpu vm requirement
|
||||
* @param vm_pci vm requirement
|
||||
* @param host to evaluate vm assgiment
|
||||
* @param n_auth number of hosts authorized for the user, incremented if needed
|
||||
* @param n_error number of requirement errors, incremented if needed
|
||||
@ -511,8 +512,8 @@ int Scheduler::set_up_pools()
|
||||
* @return true for a positive match
|
||||
*/
|
||||
static bool match_host(AclXML * acls, VirtualMachineXML* vm, int vmem, int vcpu,
|
||||
HostXML * host, int &n_auth, int& n_error, int &n_fits, int &n_matched,
|
||||
string &error)
|
||||
vector<Attribute *>& vpci, HostXML * host, int &n_auth, int& n_error,
|
||||
int &n_fits, int &n_matched, string &error)
|
||||
{
|
||||
// -------------------------------------------------------------------------
|
||||
// Filter current Hosts for resched VMs
|
||||
@ -560,7 +561,7 @@ static bool match_host(AclXML * acls, VirtualMachineXML* vm, int vmem, int vcpu,
|
||||
// -------------------------------------------------------------------------
|
||||
// Check host capacity
|
||||
// -------------------------------------------------------------------------
|
||||
if (host->test_capacity(vcpu,vmem,error) != true)
|
||||
if (host->test_capacity(vcpu, vmem, vpci, error) != true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -720,6 +721,7 @@ void Scheduler::match_schedule()
|
||||
int vm_memory;
|
||||
int vm_cpu;
|
||||
long long vm_disk;
|
||||
vector<Attribute *> vm_pci;
|
||||
|
||||
int n_resources;
|
||||
int n_matched;
|
||||
@ -750,7 +752,7 @@ void Scheduler::match_schedule()
|
||||
{
|
||||
vm = static_cast<VirtualMachineXML*>(vm_it->second);
|
||||
|
||||
vm->get_requirements(vm_cpu,vm_memory,vm_disk);
|
||||
vm->get_requirements(vm_cpu, vm_memory, vm_disk, vm_pci);
|
||||
|
||||
n_resources = 0;
|
||||
n_fits = 0;
|
||||
@ -790,8 +792,8 @@ void Scheduler::match_schedule()
|
||||
{
|
||||
host = static_cast<HostXML *>(h_it->second);
|
||||
|
||||
if (match_host(acls, vm, vm_memory, vm_cpu, host, n_auth, n_error,
|
||||
n_fits, n_matched, m_error))
|
||||
if (match_host(acls, vm, vm_memory, vm_cpu, vm_pci, host, n_auth,
|
||||
n_error, n_fits, n_matched, m_error))
|
||||
{
|
||||
vm->add_match_host(host->get_hid());
|
||||
|
||||
@ -1026,6 +1028,8 @@ void Scheduler::dispatch()
|
||||
|
||||
int cpu, mem;
|
||||
long long dsk;
|
||||
vector<Attribute *> pci;
|
||||
|
||||
int hid, dsid, cid;
|
||||
bool test_cap_result;
|
||||
|
||||
@ -1074,7 +1078,7 @@ void Scheduler::dispatch()
|
||||
}
|
||||
}
|
||||
|
||||
vm->get_requirements(cpu,mem,dsk);
|
||||
vm->get_requirements(cpu, mem, dsk, pci);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Get the highest ranked host and best System DS for it
|
||||
@ -1094,7 +1098,7 @@ void Scheduler::dispatch()
|
||||
//------------------------------------------------------------------
|
||||
// Test host capacity
|
||||
//------------------------------------------------------------------
|
||||
if (host->test_capacity(cpu,mem) != true)
|
||||
if (host->test_capacity(cpu, mem, pci) != true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1224,7 +1228,7 @@ void Scheduler::dispatch()
|
||||
vm->add_image_datastore_capacity(img_dspool);
|
||||
}
|
||||
|
||||
host->add_capacity(cpu,mem);
|
||||
host->add_capacity(vm->get_oid(), cpu, mem, pci);
|
||||
|
||||
host_vms[hid]++;
|
||||
|
||||
|
@ -281,6 +281,8 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
|
||||
ostringstream oss;
|
||||
|
||||
vector<Attribute *> pci;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Set a name if the VM has not got one and VM_ID
|
||||
// ------------------------------------------------------------------------
|
||||
@ -442,6 +444,26 @@ int VirtualMachine::insert(SqlDB * db, string& error_str)
|
||||
goto error_leases_rollback;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// PCI Devices
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
user_obj_template->remove("PCI", pci);
|
||||
|
||||
for (vector<Attribute *>::iterator it = pci.begin(); it !=pci.end(); )
|
||||
{
|
||||
if ( (*it)->type() != Attribute::VECTOR )
|
||||
{
|
||||
delete *it;
|
||||
it = pci.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj_template->set(*it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Parse the context & requirements
|
||||
// -------------------------------------------------------------------------
|
||||
@ -1649,11 +1671,14 @@ void VirtualMachine::cp_previous_history()
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk)
|
||||
void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk,
|
||||
vector<Attribute *>& pci_devs)
|
||||
{
|
||||
istringstream iss;
|
||||
float fcpu;
|
||||
|
||||
pci_devs.clear();
|
||||
|
||||
if ((get_template_attribute("MEMORY",memory) == false) ||
|
||||
(get_template_attribute("CPU",fcpu) == false))
|
||||
{
|
||||
@ -1668,6 +1693,8 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk)
|
||||
memory = memory * 1024; //now in Kilobytes
|
||||
disk = 0;
|
||||
|
||||
obj_template->get("PCI", pci_devs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -173,6 +173,13 @@ int LibVirtDriver::deployment_description_kvm(
|
||||
|
||||
const VectorAttribute * input;
|
||||
|
||||
const VectorAttribute * pci;
|
||||
|
||||
string domain = "";
|
||||
/* bus is already defined for disks */
|
||||
string slot = "";
|
||||
string func = "";
|
||||
|
||||
const VectorAttribute * features;
|
||||
|
||||
bool pae = false;
|
||||
@ -949,6 +956,50 @@ int LibVirtDriver::deployment_description_kvm(
|
||||
|
||||
attrs.clear();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// PCI Passthrough
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
num = vm->get_template_attribute("PCI",attrs);
|
||||
|
||||
for (int i=0; i < num ;i++)
|
||||
{
|
||||
pci = dynamic_cast<const VectorAttribute *>(attrs[i]);
|
||||
|
||||
if ( pci == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
domain = pci->vector_value("DOMAIN");
|
||||
bus = pci->vector_value("BUS");
|
||||
slot = pci->vector_value("SLOT");
|
||||
func = pci->vector_value("FUNCTION");
|
||||
|
||||
if ( domain.empty() || bus.empty() || slot.empty() || func.empty() )
|
||||
{
|
||||
vm->log("VMM", Log::WARNING,
|
||||
"DOMAIN, BUS, SLOT and FUNC must be defined for PCI "
|
||||
"passthrough. Ignored.");
|
||||
continue;
|
||||
}
|
||||
|
||||
file << "\t\t<hostdev mode='subsystem' type='pci' managed='yes'>";
|
||||
file << endl;
|
||||
file << "\t\t\t<source>" << endl;
|
||||
|
||||
file << "\t\t\t\t<address ";
|
||||
file << "domain='0x" << domain << "' ";
|
||||
file << "bus='0x" << bus << "' ";
|
||||
file << "slot='0x" << slot << "' ";
|
||||
file << "function='0x" << func << "'/>" << endl;
|
||||
|
||||
file << "\t\t\t</source>" << endl;
|
||||
file << "\t\t</hostdev>" << endl;
|
||||
}
|
||||
|
||||
attrs.clear();
|
||||
|
||||
file << "\t</devices>" << endl;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user