mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-15 18:50:09 +03:00
feature #3208: Add PCI device set to the HostShare
This commit is contained in:
parent
6b8a16fc76
commit
e04ee43aa3
@ -20,22 +20,149 @@
|
||||
#include "ObjectXML.h"
|
||||
#include "Template.h"
|
||||
#include <time.h>
|
||||
|
||||
using namespace std;
|
||||
#include <set>
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
class HostShareTemplate : public Template
|
||||
class HostShareDatastore : public Template
|
||||
{
|
||||
public:
|
||||
HostShareTemplate(const char * name) : Template(false, '=', name){};
|
||||
HostShareDatastore() : Template(false, '=', "DATASTORE"){};
|
||||
|
||||
~HostShareTemplate(){};
|
||||
virtual ~HostShareDatastore(){};
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/**
|
||||
* This class represents a PCI DEVICE list for the host. The list is in the
|
||||
* form:
|
||||
* <PCI>
|
||||
* <TYPE>: Three 4-hex digits groups representing <vendor>:<device>:<class>
|
||||
* <DESCRIPTION>: The corresponding device description
|
||||
* <ADDRESS>: PCI address, bus, slot and function
|
||||
*/
|
||||
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 wether 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)
|
||||
{
|
||||
return test_set(devs, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the requested devices to the given VM. The assgined 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
|
||||
* assgined devices.
|
||||
* @param vmid of the VM
|
||||
*/
|
||||
void add(vector<Attribute *> &devs, int vmid)
|
||||
{
|
||||
test_set(devs, vmid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the VM assigment 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);
|
||||
|
||||
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. It will assgin 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 assgined set of addresses already assgined 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);
|
||||
|
||||
/**
|
||||
* 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 assgined.
|
||||
*/
|
||||
bool test_set(vector<Attribute *> &devs, int vmid);
|
||||
|
||||
/**
|
||||
* 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...
|
||||
@ -125,7 +252,10 @@ public:
|
||||
|
||||
void set_ds_monitorization(const vector<Attribute*> &ds_att);
|
||||
|
||||
void set_pci_monitorization(const vector<Attribute*> &pci_att);
|
||||
void set_pci_monitorization(vector<Attribute*> &pci_att)
|
||||
{
|
||||
pci.set_monitorization(pci_att);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -147,8 +277,8 @@ private:
|
||||
|
||||
long long running_vms;/**< Number of running VMs in this Host */
|
||||
|
||||
HostShareTemplate ds_template;
|
||||
HostShareTemplate pci_template;
|
||||
HostShareDatastore ds;
|
||||
HostSharePCI pci;
|
||||
|
||||
// ----------------------------------------
|
||||
// Friends
|
||||
|
@ -15,7 +15,6 @@
|
||||
/* ------------------------------------------------------------------------*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@ -23,6 +22,228 @@
|
||||
|
||||
#include "HostShare.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* ************************************************************************ */
|
||||
/* HostSharePCI */
|
||||
/* ************************************************************************ */
|
||||
|
||||
int HostSharePCI::from_xml_node(const xmlNodePtr node)
|
||||
{
|
||||
int rc = 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_set(unsigned int vendor_id, unsigned int device_id,
|
||||
unsigned int class_id, VectorAttribute * devreq, int vmid,
|
||||
std::set<string>& assigned)
|
||||
{
|
||||
map<string, PCIDevice *>::iterator it;
|
||||
|
||||
for (it=pci_devices.begin(); it!=pci_devices.end(); it++)
|
||||
{
|
||||
PCIDevice * dev = it->second;
|
||||
|
||||
if (dev->class_id == class_id &&
|
||||
dev->vendor_id == vendor_id &&
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
attrs->vector_value("VMID", vmid);
|
||||
attrs->vector_value("ADDRESS", address);
|
||||
};
|
||||
|
||||
/* ************************************************************************ */
|
||||
/* HostShare :: Constructor/Destructor */
|
||||
/* ************************************************************************ */
|
||||
@ -42,8 +263,8 @@ HostShare::HostShare(long long _max_disk,long long _max_mem,long long _max_cpu):
|
||||
used_mem(0),
|
||||
used_cpu(0),
|
||||
running_vms(0),
|
||||
ds_template("DATASTORES"),
|
||||
pci_template("PCI_DEVICES"){};
|
||||
ds(),
|
||||
pci(){};
|
||||
|
||||
ostream& operator<<(ostream& os, HostShare& hs)
|
||||
{
|
||||
@ -76,8 +297,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(ds_xml)
|
||||
<< pci_template.to_xml(pci_xml)
|
||||
<< ds.to_xml(ds_xml)
|
||||
<< pci.to_xml(pci_xml)
|
||||
<< "</HOST_SHARE>";
|
||||
|
||||
xml = oss.str();
|
||||
@ -123,7 +344,7 @@ 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);
|
||||
|
||||
@ -143,7 +364,7 @@ int HostShare::from_xml_node(const xmlNodePtr node)
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc += pci_template.from_xml_node( content[0] );
|
||||
rc += pci.from_xml_node( content[0] );
|
||||
|
||||
ObjectXML::free_nodes(content);
|
||||
|
||||
@ -165,26 +386,14 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void HostShare::set_pci_monitorization(const vector<Attribute*> &pci_att)
|
||||
{
|
||||
vector<Attribute*>::const_iterator it;
|
||||
|
||||
pci_template.erase("PCI");
|
||||
|
||||
for (it = pci_att.begin(); it != pci_att.end(); it++)
|
||||
{
|
||||
pci_template.set(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user