From 6b8a16fc76edc793db11ec031b48f10b138c3b6f Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Mon, 17 Aug 2015 23:14:15 +0200 Subject: [PATCH 01/18] feature #3028: Adds PCI_DEVICES to HostShare --- include/HostShare.h | 5 ++++- src/host/Host.cc | 5 +++++ src/host/HostShare.cc | 49 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/include/HostShare.h b/include/HostShare.h index a929ad9fc5..4d674e5d1e 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -29,7 +29,7 @@ using namespace std; class HostShareTemplate : public Template { public: - HostShareTemplate() : Template(false,'=',"DATASTORES"){}; + HostShareTemplate(const char * name) : Template(false, '=', name){}; ~HostShareTemplate(){}; }; @@ -125,6 +125,8 @@ public: void set_ds_monitorization(const vector &ds_att); + void set_pci_monitorization(const vector &pci_att); + private: long long disk_usage; /**< Disk allocated to VMs (in MB). */ @@ -146,6 +148,7 @@ private: long long running_vms;/**< Number of running VMs in this Host */ HostShareTemplate ds_template; + HostShareTemplate pci_template; // ---------------------------------------- // Friends diff --git a/src/host/Host.cc b/src/host/Host.cc index 843ecb4caf..8d3273a005 100644 --- a/src/host/Host.cc +++ b/src/host/Host.cc @@ -256,6 +256,7 @@ int Host::update_info(Template &tmpl, vector::iterator it; vector vm_att; vector ds_att; + vector pci_att; vector 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; } diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 64b0bbb6a2..94d2850874 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -41,7 +41,9 @@ HostShare::HostShare(long long _max_disk,long long _max_mem,long long _max_cpu): used_disk(0), used_mem(0), used_cpu(0), - running_vms(0){}; + running_vms(0), + ds_template("DATASTORES"), + pci_template("PCI_DEVICES"){}; ostream& operator<<(ostream& os, HostShare& hs) { @@ -57,7 +59,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 << "" @@ -74,7 +76,8 @@ string& HostShare::to_xml(string& xml) const << "" << used_mem << "" << "" << used_cpu << "" << ""<" - << ds_template.to_xml(template_xml) + << ds_template.to_xml(ds_xml) + << pci_template.to_xml(pci_xml) << ""; xml = oss.str(); @@ -131,9 +134,33 @@ int HostShare::from_xml_node(const xmlNodePtr node) return -1; } + // ------------ DS Template --------------- + + ObjectXML::get_nodes("/HOST_SHARE/PCI_DEVICES", content); + + if( content.empty()) + { + return -1; + } + + rc += pci_template.from_xml_node( content[0] ); + + ObjectXML::free_nodes(content); + + content.clear(); + + if (rc != 0) + { + return -1; + } + return 0; } + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + void HostShare::set_ds_monitorization(const vector &ds_att) { vector::const_iterator it; @@ -145,3 +172,19 @@ void HostShare::set_ds_monitorization(const vector &ds_att) ds_template.set(*it); } } + +/* ------------------------------------------------------------------------ */ +/* ------------------------------------------------------------------------ */ + +void HostShare::set_pci_monitorization(const vector &pci_att) +{ + vector::const_iterator it; + + pci_template.erase("PCI"); + + for (it = pci_att.begin(); it != pci_att.end(); it++) + { + pci_template.set(*it); + } +} + From e04ee43aa38103bf46b03e5e79f9dd0e9ab8699d Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 20 Aug 2015 17:39:56 +0200 Subject: [PATCH 02/18] feature #3208: Add PCI device set to the HostShare --- include/HostShare.h | 150 +++++++++++++++++++++++-- src/host/HostShare.cc | 251 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 370 insertions(+), 31 deletions(-) diff --git a/include/HostShare.h b/include/HostShare.h index 4d674e5d1e..9152b57b34 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -20,22 +20,149 @@ #include "ObjectXML.h" #include "Template.h" #include - -using namespace std; +#include /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -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: + * + * : Three 4-hex digits groups representing :: + * : The corresponding device description + *
: PCI address, bus, slot and function + */ +class HostSharePCI : public Template +{ +public: + + HostSharePCI() : Template(false, '=', "PCI_DEVICES"){}; + + virtual ~HostSharePCI() + { + map::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 &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 &devs, int vmid) + { + test_set(devs, vmid); + } + + /** + * Remove the VM assigment from the PCI device list + */ + void del(const vector &devs); + + /** + * Updates the PCI list with monitor data, it will create or + * remove PCIDevices as needed. + */ + void set_monitorization(vector &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 &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 &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 pci_devices; +}; /** * The HostShare class. It represents a logical partition of a host... @@ -125,7 +252,10 @@ public: void set_ds_monitorization(const vector &ds_att); - void set_pci_monitorization(const vector &pci_att); + void set_pci_monitorization(vector &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 diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 94d2850874..50525d7f16 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -15,7 +15,6 @@ /* ------------------------------------------------------------------------*/ #include -#include #include #include @@ -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 devices; + + int num_devs = get("PCI", devices); + + for (int i=0; i < num_devs; i++) + { + VectorAttribute * pci = dynamic_cast(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& assigned) +{ + map::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 &devs, int vmid) +{ + vector::iterator it; + std::set assigned; + + unsigned int vendor_id, device_id, class_id; + + for ( it=devs.begin(); it!= devs.end(); it++) + { + VectorAttribute * pci = dynamic_cast(*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 &devs) +{ + vector::const_iterator it; + map::iterator pci_it; + + for ( it=devs.begin(); it!= devs.end(); it++) + { + const VectorAttribute * pci = dynamic_cast(*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 &pci_att) +{ + vector::iterator it; + map::iterator pci_it; + + string address; + + for (it = pci_att.begin(); it != pci_att.end(); it++) + { + VectorAttribute * pci = dynamic_cast(*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_cpu << "" << ""<" - << ds_template.to_xml(ds_xml) - << pci_template.to_xml(pci_xml) + << ds.to_xml(ds_xml) + << pci.to_xml(pci_xml) << ""; 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 &ds_att) { vector::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 &pci_att) -{ - vector::const_iterator it; - - pci_template.erase("PCI"); - - for (it = pci_att.begin(); it != pci_att.end(); it++) - { - pci_template.set(*it); - } -} - From 70433a6d7b775ba376b9adbf2c76a824a93ccf03 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Thu, 20 Aug 2015 18:20:10 +0200 Subject: [PATCH 03/18] feature #3028: kvm probe to get PCI devices --- install.sh | 1 + src/im_mad/remotes/kvm-probes.d/pci.rb | 114 +++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100755 src/im_mad/remotes/kvm-probes.d/pci.rb diff --git a/install.sh b/install.sh index ad3cad4733..76a1e0b5b7 100755 --- a/install.sh +++ b/install.sh @@ -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" diff --git a/src/im_mad/remotes/kvm-probes.d/pci.rb b/src/im_mad/remotes/kvm-probes.d/pci.rb new file mode 100755 index 0000000000..565cc25569 --- /dev/null +++ b/src/im_mad/remotes/kvm-probes.d/pci.rb @@ -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 []:[][:] +# +# 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 + + + From 00427a09507613c41532281cc5989707a03cafd5 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Thu, 20 Aug 2015 23:22:02 +0200 Subject: [PATCH 04/18] feature #3028: Fix PCI set bugs --- include/HostShare.h | 2 +- src/host/HostShare.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/HostShare.h b/include/HostShare.h index 9152b57b34..ccca9ff98f 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -28,7 +28,7 @@ class HostShareDatastore : public Template { public: - HostShareDatastore() : Template(false, '=', "DATASTORE"){}; + HostShareDatastore() : Template(false, '=', "DATASTORES"){}; virtual ~HostShareDatastore(){}; }; diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 50525d7f16..916a77db47 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -30,7 +30,7 @@ using namespace std; int HostSharePCI::from_xml_node(const xmlNodePtr node) { - int rc = from_xml_node(node); + int rc = Template::from_xml_node(node); if (rc != 0) { From 67ec62e0d45a63b4dc2b6c8293f23203e2d5895a Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 21 Aug 2015 01:08:28 +0200 Subject: [PATCH 05/18] feature #3028: Add PCI capacity when deploying a VM --- include/Host.h | 6 ++-- include/HostPool.h | 6 ++-- include/HostShare.h | 7 ++++- include/VirtualMachine.h | 4 ++- src/dm/DispatchManagerActions.cc | 9 ++++-- src/lcm/LifeCycleActions.cc | 29 +++++++++++-------- src/lcm/LifeCycleStates.cc | 40 ++++++++++++++++---------- src/rm/RequestManagerVirtualMachine.cc | 12 +++++--- src/vm/VirtualMachine.cc | 27 ++++++++++++++++- 9 files changed, 99 insertions(+), 41 deletions(-) diff --git a/include/Host.h b/include/Host.h index a4c241fa84..71e5856f2e 100644 --- a/include/Host.h +++ b/include/Host.h @@ -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 devicesneeded 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 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 { diff --git a/include/HostPool.h b/include/HostPool.h index 8a19172cc4..78bf1c7750 100644 --- a/include/HostPool.h +++ b/include/HostPool.h @@ -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 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); diff --git a/include/HostShare.h b/include/HostShare.h index ccca9ff98f..862b7d2ef3 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -180,16 +180,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 pci_devs) { cpu_usage += cpu; mem_usage += mem; disk_usage += disk; + pci.add(pci_devs, vmid); + running_vms++; } diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index a6ec0ed42f..a828effcfa 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -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& pci_dev); /** * Checks if the resize parameters are valid diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 26b36619bf..f491c81098 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -92,10 +92,11 @@ int DispatchManager::import ( time_t the_time = time(0); int cpu, mem, disk; + vector 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); @@ -770,6 +771,8 @@ int DispatchManager::finalize( VirtualMachine * vm; ostringstream oss; + vector pci; + VirtualMachine::VmState state; vm = vmpool->get(vid,true); @@ -790,7 +793,7 @@ int DispatchManager::finalize( case VirtualMachine::POWEROFF: int cpu, mem, disk; - 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); tm->trigger(TransferManager::EPILOG_DELETE,vid); diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index 84785d7dbb..1bf670501d 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -35,6 +35,7 @@ void LifeCycleManager::deploy_action(int vid) { time_t thetime = time(0); int cpu,mem,disk; + vector 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 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,9 +281,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); hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk); @@ -321,9 +324,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); hpool->del_capacity(vm->get_previous_hid(), vm->get_oid(), cpu, mem, disk); @@ -359,7 +362,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 pci; //---------------------------------------------------- // MIGRATE STATE @@ -377,9 +381,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 +849,7 @@ void LifeCycleManager::clean_action(int vid) void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& image_id) { int cpu, mem, disk; + vector pci; time_t the_time = time(0); VirtualMachine::LcmState state = vm->get_lcm_state(); @@ -873,7 +878,7 @@ 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); + vm->get_requirements(cpu, mem, disk, pci); hpool->del_capacity(vm->get_hid(), vm->get_oid(), cpu, mem, disk); switch (state) diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 9691b5c258..02a7e3b26e 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -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 pci; + + time_t the_time = time(0); //---------------------------------------------------- // PROLOG_MIGRATE STATE @@ -66,7 +68,7 @@ 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); @@ -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 pci; + + time_t the_time = time(0); //---------------------------------------------------- // RUNNING STATE FROM SAVE_MIGRATE @@ -171,7 +175,7 @@ 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); @@ -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 pci; + + time_t the_time = time(0); vm->set_running_stime(the_time); @@ -275,7 +281,7 @@ 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); @@ -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 pci; + + time_t the_time = time(0); //---------------------------------------------------- // RUNNING STATE FROM MIGRATE @@ -357,7 +365,7 @@ 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); @@ -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 pci; + + time_t the_time = time(0); + int cpu,mem,disk; VirtualMachine::LcmState state; DispatchManager::Actions action; @@ -859,7 +869,7 @@ 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); diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index b02a5bc42e..de716596a6 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -816,10 +816,12 @@ void VirtualMachineDeploy::request_execute(xmlrpc_c::paramList const& paramList, if (enforce) { - int cpu, mem, disk; + int cpu, mem, disk; + vector pci; + string error; - vm->get_requirements(cpu, mem, disk); + vm->get_requirements(cpu, mem, disk, pci); vm->unlock(); @@ -1033,10 +1035,12 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList // Check the host has enough capacity if (enforce) { - int cpu, mem, disk; + int cpu, mem, disk; + vector pci; + string error; - vm->get_requirements(cpu, mem, disk); + vm->get_requirements(cpu, mem, disk, pci); vm->unlock(); diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index dc9bddb73c..d6bbb22767 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -281,6 +281,8 @@ int VirtualMachine::insert(SqlDB * db, string& error_str) ostringstream oss; + vector 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::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& pci_devs) { istringstream iss; float fcpu; + obj_template->get("PCI", pci_devs); + if ((get_template_attribute("MEMORY",memory) == false) || (get_template_attribute("CPU",fcpu) == false)) { From 17f2380e40a061fb9bea32d3955872d30df523e8 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 21 Aug 2015 10:46:36 +0200 Subject: [PATCH 06/18] feature #3028: Fix PCI device assignment --- src/host/HostShare.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 916a77db47..52f58c4cc1 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -76,10 +76,10 @@ bool HostSharePCI::test_set(unsigned int vendor_id, unsigned int device_id, { PCIDevice * dev = it->second; - if (dev->class_id == class_id && - dev->vendor_id == vendor_id && - dev->device_id == device_id && - dev->vmid == -1 && + 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); From c4c64164584fd4e635ce3b6a6406aac812e22328 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 21 Aug 2015 12:00:19 +0200 Subject: [PATCH 07/18] feature #3028: Delete pci devices from host when removing the VM. Always include VMID in PCI elements --- include/Host.h | 8 +++++--- include/HostPool.h | 6 ++++-- include/HostShare.h | 5 ++++- src/dm/DispatchManagerActions.cc | 2 +- src/host/HostShare.cc | 6 +++++- src/lcm/LifeCycleActions.cc | 12 +++++++----- src/lcm/LifeCycleStates.cc | 10 +++++----- 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/include/Host.h b/include/Host.h index 71e5856f2e..b715b985b4 100644 --- a/include/Host.h +++ b/include/Host.h @@ -379,7 +379,7 @@ public: * @param cpu needed by the VM (percentage) * @param mem needed by the VM (in KB) * @param disk needed by the VM - * @param pci devicesneeded by th 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, @@ -406,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 pci) { if ( vm_collection.del_collection_id(vm_id) == 0 ) { - host_share.del(cpu,mem,disk); + host_share.del(cpu, mem, disk, pci); } else { diff --git a/include/HostPool.h b/include/HostPool.h index 78bf1c7750..fa2c05a2c6 100644 --- a/include/HostPool.h +++ b/include/HostPool.h @@ -156,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 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); diff --git a/include/HostShare.h b/include/HostShare.h index 862b7d2ef3..5b9bd3565b 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -216,13 +216,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 pci_devs) { cpu_usage -= cpu; mem_usage -= mem; disk_usage -= disk; + pci.del(pci_devs); + running_vms--; } diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index f491c81098..5db5879821 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -794,7 +794,7 @@ int DispatchManager::finalize( int 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); tm->trigger(TransferManager::EPILOG_DELETE,vid); finalize_cleanup(vm); diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 52f58c4cc1..97556620a1 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -240,7 +240,11 @@ HostSharePCI::PCIDevice::PCIDevice(VectorAttribute * _attrs) device_id = get_pci_value("DEVICE", attrs); class_id = get_pci_value("CLASS", attrs); - attrs->vector_value("VMID", vmid); + if (attrs->vector_value("VMID", vmid) == -1) + { + attrs->replace("VMID", -1); + } + attrs->vector_value("ADDRESS", address); }; diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index 1bf670501d..b68f30873e 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -285,7 +285,8 @@ void LifeCycleManager::migrate_action(int vid) 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); //---------------------------------------------------- @@ -328,7 +329,8 @@ void LifeCycleManager::migrate_action(int vid) 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); //---------------------------------------------------- @@ -879,7 +881,7 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, int& imag vm->set_reason(History::USER); 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); switch (state) { @@ -1010,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); @@ -1036,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); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 02a7e3b26e..44e9baeab0 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -70,7 +70,7 @@ void LifeCycleManager::save_success_action(int vid) 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); //---------------------------------------------------- @@ -177,7 +177,7 @@ void LifeCycleManager::save_failure_action(int vid) 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); @@ -283,7 +283,7 @@ void LifeCycleManager::deploy_success_action(int vid) 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); @@ -367,7 +367,7 @@ void LifeCycleManager::deploy_failure_action(int vid) 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 @@ -871,7 +871,7 @@ void LifeCycleManager::epilog_success_action(int vid) 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); //---------------------------------------------------- From 6d8ea1a337e5b1fe7420e734f931086fd38f1f99 Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 21 Aug 2015 13:46:10 +0200 Subject: [PATCH 08/18] feature #3028: Print HostShare and HostXML into streams. Scheduler now parses PCI device lists --- include/HostShare.h | 6 +++ src/host/HostShare.cc | 28 +++++++++-- src/scheduler/include/HostXML.h | 9 ++++ src/scheduler/src/pool/HostPoolXML.cc | 6 ++- src/scheduler/src/pool/HostXML.cc | 68 ++++++++++++++++++++++----- src/scheduler/src/sched/SConstruct | 1 + 6 files changed, 100 insertions(+), 18 deletions(-) diff --git a/include/HostShare.h b/include/HostShare.h index 5b9bd3565b..42c38deb6e 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -99,6 +99,12 @@ public: */ void set_monitorization(vector &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 diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 97556620a1..1ca35ae7ed 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -233,6 +233,9 @@ unsigned int HostSharePCI::get_pci_value(const char * name, return pci_value; } +/* ------------------------------------------------------------------------*/ +/* ------------------------------------------------------------------------*/ + HostSharePCI::PCIDevice::PCIDevice(VectorAttribute * _attrs) : vmid(-1), attrs(_attrs) { @@ -248,6 +251,27 @@ HostSharePCI::PCIDevice::PCIDevice(VectorAttribute * _attrs) attrs->vector_value("ADDRESS", address); }; +/* ------------------------------------------------------------------------*/ +/* ------------------------------------------------------------------------*/ + +ostream& operator<<(ostream& os, const HostSharePCI& pci) +{ + map::const_iterator it; + + for (it=pci.pci_devices.begin(); it!=pci.pci_devices.end(); it++) + { + HostSharePCI::PCIDevice * dev = it->second; + + os << endl << "CLASS : " << dev->class_id; + os << endl << "VENDOR : " << dev->vendor_id; + os << endl << "DEVICE : " << dev->device_id; + os << endl << "ADDRESS : " << dev->address; + os << endl << "VMID : " << dev->vmid; + os << endl; + } + + return os; +} /* ************************************************************************ */ /* HostShare :: Constructor/Destructor */ /* ************************************************************************ */ @@ -266,9 +290,7 @@ HostShare::HostShare(long long _max_disk,long long _max_mem,long long _max_cpu): used_disk(0), used_mem(0), used_cpu(0), - running_vms(0), - ds(), - pci(){}; + running_vms(0){}; ostream& operator<<(ostream& os, HostShare& hs) { diff --git a/src/scheduler/include/HostXML.h b/src/scheduler/include/HostXML.h index fb9cb2504d..4985076d71 100644 --- a/src/scheduler/include/HostXML.h +++ b/src/scheduler/include/HostXML.h @@ -20,6 +20,7 @@ #include #include "ObjectXML.h" +#include "HostShare.h" using namespace std; @@ -131,6 +132,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 +157,8 @@ private: bool public_cloud; + HostSharePCI pci; + // Configuration attributes static const char *host_paths[]; /**< paths for search function */ diff --git a/src/scheduler/src/pool/HostPoolXML.cc b/src/scheduler/src/pool/HostPoolXML.cc index df026290ea..cf54faa943 100644 --- a/src/scheduler/src/pool/HostPoolXML.cc +++ b/src/scheduler/src/pool/HostPoolXML.cc @@ -29,11 +29,13 @@ int HostPoolXML::set_up() { oss << "Discovered Hosts (enabled):" << endl; - map::iterator it; + map::iterator it; for (it=objects.begin();it!=objects.end();it++) { - oss << " " << it->first; + HostXML * h = dynamic_cast(it->second); + + oss << *h << endl; } } else diff --git a/src/scheduler/src/pool/HostXML.cc b/src/scheduler/src/pool/HostXML.cc index 17ce4fe201..df64375239 100644 --- a/src/scheduler/src/pool/HostXML.cc +++ b/src/scheduler/src/pool/HostXML.cc @@ -36,36 +36,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 ds_ids = (*this)["/HOST/HOST_SHARE/DATASTORES/DS/ID"]; - vector ds_free_mb = (*this)["/HOST/HOST_SHARE/DATASTORES/DS/FREE_MB"]; + //-------------------- HostShare Datastores ------------------------------ + vector ds_ids = (*this)["/HOST/HOST_SHARE/DATASTORES/DS/ID"]; + vector 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 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; } @@ -169,3 +183,31 @@ void HostXML::add_ds_capacity(int dsid, long long vm_disk_mb) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +ostream& operator<<(ostream& o, const HostXML& p) +{ + map::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 << "DATASTORES" << endl; + o << "----------" << endl; + for (it = p.ds_free_disk.begin() ; it != p.ds_free_disk.end() ; it++) + { + o <<"\tDSID: "<< it->first << "\t\tFREE_MB: " << it->second << endl; + } + + o << "PCI DEVICES"<< endl; + o << "-----------"<< endl; + o << p.pci; + + return o; +} diff --git a/src/scheduler/src/sched/SConstruct b/src/scheduler/src/sched/SConstruct index c7f4c05836..1b09ba5a6d 100644 --- a/src/scheduler/src/sched/SConstruct +++ b/src/scheduler/src/sched/SConstruct @@ -39,6 +39,7 @@ sched_env.Prepend(LIBS=[ 'nebula_core', 'nebula_template', 'nebula_vm', + 'nebula_host', 'crypto', 'xml2' ]) From 371a96c5ed558bae8bb1045e69921c995545e777 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Fri, 21 Aug 2015 13:48:09 +0200 Subject: [PATCH 09/18] feature #3028: show pci devices in onehost show --- src/cli/one_helper/onehost_helper.rb | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/cli/one_helper/onehost_helper.rb b/src/cli/one_helper/onehost_helper.rb index 44f262daa4..60f8e56be2 100644 --- a/src/cli/one_helper/onehost_helper.rb +++ b/src/cli/one_helper/onehost_helper.rb @@ -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 From 2b7a2e9915c7df5432cb92043e97954c3cff3649 Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Fri, 21 Aug 2015 16:11:14 +0200 Subject: [PATCH 10/18] feature #3028: add pci passthrough to deployment file --- src/vmm/LibVirtDriverKVM.cc | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/vmm/LibVirtDriverKVM.cc b/src/vmm/LibVirtDriverKVM.cc index b9f4584e51..8ea47ff084 100644 --- a/src/vmm/LibVirtDriverKVM.cc +++ b/src/vmm/LibVirtDriverKVM.cc @@ -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,42 @@ 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(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"); + + file << "\t\t"; + file << endl; + file << "\t\t\t" << endl; + + file << "\t\t\t\t
" << endl; + + file << "\t\t\t" << endl; + file << "\t\t" << endl; + } + + attrs.clear(); + file << "\t" << endl; // ------------------------------------------------------------------------ From b1baa06f2bc421c11049915facc7ffb023c68a9b Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Fri, 21 Aug 2015 17:23:08 +0200 Subject: [PATCH 11/18] feature #3028: Scheduler check and set PCI device requests --- src/host/HostShare.cc | 21 ++++--- src/scheduler/include/HostXML.h | 14 +++-- src/scheduler/include/VirtualMachineXML.h | 3 +- src/scheduler/src/pool/HostXML.cc | 60 ++++++++++++------- .../src/pool/VirtualMachinePoolXML.cc | 6 +- src/scheduler/src/pool/VirtualMachineXML.cc | 12 +++- src/scheduler/src/sched/Scheduler.cc | 22 ++++--- 7 files changed, 95 insertions(+), 43 deletions(-) diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 1ca35ae7ed..8eb017b083 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -18,7 +18,8 @@ #include #include -#include +#include +#include #include "HostShare.h" @@ -258,16 +259,22 @@ ostream& operator<<(ostream& os, const HostSharePCI& pci) { map::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 << endl << "CLASS : " << dev->class_id; - os << endl << "VENDOR : " << dev->vendor_id; - os << endl << "DEVICE : " << dev->device_id; - os << endl << "ADDRESS : " << dev->address; - os << endl << "VMID : " << dev->vmid; - os << endl; + 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; diff --git a/src/scheduler/include/HostXML.h b/src/scheduler/include/HostXML.h index 4985076d71..15576ac6f7 100644 --- a/src/scheduler/include/HostXML.h +++ b/src/scheduler/include/HostXML.h @@ -51,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 byt 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 &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 byt 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 &p) { string tmp_st; - return test_capacity(cpu, mem, tmp_st); + return test_capacity(cpu, mem, p, tmp_st); }; /** @@ -75,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 &p) { cpu_usage += cpu; mem_usage += mem; + pci.add(p, vmid); + running_vms++; }; diff --git a/src/scheduler/include/VirtualMachineXML.h b/src/scheduler/include/VirtualMachineXML.h index 4539608df3..521edf8a48 100644 --- a/src/scheduler/include/VirtualMachineXML.h +++ b/src/scheduler/include/VirtualMachineXML.h @@ -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 &pci); map get_storage_usage(); diff --git a/src/scheduler/src/pool/HostXML.cc b/src/scheduler/src/pool/HostXML.cc index df64375239..a6cc8a59ff 100644 --- a/src/scheduler/src/pool/HostXML.cc +++ b/src/scheduler/src/pool/HostXML.cc @@ -16,6 +16,8 @@ #include #include +#include +#include #include "HostXML.h" #include "NebulaUtil.h" @@ -125,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& 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."; + } } } @@ -198,16 +216,18 @@ ostream& operator<<(ostream& o, const HostXML& p) o << "RUNNING_VMS : " << p.running_vms << endl; o << "PUBLIC : " << p.public_cloud << endl; - o << "DATASTORES" << endl; - o << "----------" << 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 <<"\tDSID: "<< it->first << "\t\tFREE_MB: " << it->second << endl; + o << right << setw(5) << it->first << " " + << right << setw(15)<< it->second<< " " << endl; } - o << "PCI DEVICES"<< endl; - o << "-----------"<< endl; - o << p.pci; + o << endl << p.pci; return o; } diff --git a/src/scheduler/src/pool/VirtualMachinePoolXML.cc b/src/scheduler/src/pool/VirtualMachinePoolXML.cc index 16c9a23e3e..319b207f29 100644 --- a/src/scheduler/src/pool/VirtualMachinePoolXML.cc +++ b/src/scheduler/src/pool/VirtualMachinePoolXML.cc @@ -39,6 +39,7 @@ int VirtualMachinePoolXML::set_up() << right << setw(8) << "VM" << " " << right << setw(4) << "CPU" << " " << right << setw(11) << "Memory" << " " + << right << setw(2) << "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 pci; + string action = "DEPLOY"; VirtualMachineXML * vm = static_cast(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(2) << pci.size() << " " << right << setw(11) << disk << " "; map ds_usage = vm->get_storage_usage(); diff --git a/src/scheduler/src/pool/VirtualMachineXML.cc b/src/scheduler/src/pool/VirtualMachineXML.cc index b6ab5d2c8d..9532c414f1 100644 --- a/src/scheduler/src/pool/VirtualMachineXML.cc +++ b/src/scheduler/src/pool/VirtualMachineXML.cc @@ -202,8 +202,18 @@ 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 &pci) { + if (vm_template != 0) + { + vm_template->get("PCI", pci); + } + else + { + pci.clear(); + } + if (this->memory == 0 || this->cpu == 0) { cpu = 0; diff --git a/src/scheduler/src/sched/Scheduler.cc b/src/scheduler/src/sched/Scheduler.cc index e059b86d3a..0ed226f76e 100644 --- a/src/scheduler/src/sched/Scheduler.cc +++ b/src/scheduler/src/sched/Scheduler.cc @@ -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& 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 vm_pci; int n_resources; int n_matched; @@ -750,7 +752,7 @@ void Scheduler::match_schedule() { vm = static_cast(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(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 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]++; From 17c33241a689a4aa070509ee662bf5e802bfc51c Mon Sep 17 00:00:00 2001 From: "Ruben S. Montero" Date: Sat, 22 Aug 2015 17:00:55 +0200 Subject: [PATCH 12/18] feature #3028: Add comments to PCI format. Init pci list in get_* methods --- include/HostShare.h | 15 ++++++++++++--- src/host/HostShare.cc | 4 ++-- src/scheduler/src/pool/VirtualMachineXML.cc | 6 ++---- src/vm/VirtualMachine.cc | 2 ++ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/HostShare.h b/include/HostShare.h index 42c38deb6e..e62907f1eb 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -37,9 +37,18 @@ public: * This class represents a PCI DEVICE list for the host. The list is in the * form: * - * : Three 4-hex digits groups representing :: - * : The corresponding device description - *
: PCI address, bus, slot and function + * PCI address domain + * PCI address bus + * PCI address slot + * PCI address function + *
PCI address, bus, slot and function + * ID of PCI device vendor + * ID of PCI device + * ID of PCI device class + * 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 { diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 8eb017b083..130b32b6bd 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -368,7 +368,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); @@ -388,7 +388,7 @@ int HostShare::from_xml_node(const xmlNodePtr node) return -1; } - // ------------ DS Template --------------- + // ------------ PCI Devices --------------- ObjectXML::get_nodes("/HOST_SHARE/PCI_DEVICES", content); diff --git a/src/scheduler/src/pool/VirtualMachineXML.cc b/src/scheduler/src/pool/VirtualMachineXML.cc index 9532c414f1..97c26a1888 100644 --- a/src/scheduler/src/pool/VirtualMachineXML.cc +++ b/src/scheduler/src/pool/VirtualMachineXML.cc @@ -205,14 +205,12 @@ ostream& operator<<(ostream& os, VirtualMachineXML& vm) void VirtualMachineXML::get_requirements (int& cpu, int& memory, long long& disk, vector &pci) { + pci.clear(); + if (vm_template != 0) { vm_template->get("PCI", pci); } - else - { - pci.clear(); - } if (this->memory == 0 || this->cpu == 0) { diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index d6bbb22767..8f738cdb58 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1677,6 +1677,8 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk, istringstream iss; float fcpu; + pci_devs.clear(); + obj_template->get("PCI", pci_devs); if ((get_template_attribute("MEMORY",memory) == false) || From a2e7ccffe18d6a27bb76570b666ebd75c69f9112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Tue, 25 Aug 2015 10:43:28 +0200 Subject: [PATCH 13/18] Feature #3028: Add PCI_DEVICES to onedb migrator --- src/onedb/local/4.13.80_to_4.13.85.rb | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/onedb/local/4.13.80_to_4.13.85.rb b/src/onedb/local/4.13.80_to_4.13.85.rb index 551438276d..244492b022 100644 --- a/src/onedb/local/4.13.80_to_4.13.85.rb +++ b/src/onedb/local/4.13.80_to_4.13.85.rb @@ -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 From 18946ff3b87c9f0a83eb89f72dc89bd1905521a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Tue, 25 Aug 2015 13:17:42 +0200 Subject: [PATCH 14/18] Feature #3028: Add PCI dev checks to onedb fsck --- src/onedb/fsck.rb | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/onedb/fsck.rb b/src/onedb/fsck.rb index 6e23dc8a8a..aec7dd5343 100644 --- a/src/onedb/fsck.rb +++ b/src/onedb/fsck.rb @@ -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 } From 415e0b6c965b1c274daf3e97505cffbd79afcd8a Mon Sep 17 00:00:00 2001 From: Javi Fontan Date: Wed, 26 Aug 2015 11:40:52 +0200 Subject: [PATCH 15/18] feature #3028: check all needed pci params for deployment file --- src/vmm/LibVirtDriverKVM.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vmm/LibVirtDriverKVM.cc b/src/vmm/LibVirtDriverKVM.cc index 8ea47ff084..5d9ac9cb57 100644 --- a/src/vmm/LibVirtDriverKVM.cc +++ b/src/vmm/LibVirtDriverKVM.cc @@ -976,6 +976,14 @@ int LibVirtDriver::deployment_description_kvm( 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"; file << endl; file << "\t\t\t" << endl; From a0a9504f1768b30bbbc883dae5bba96c960b668d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 26 Aug 2015 11:05:15 +0200 Subject: [PATCH 16/18] Feature #3028: Add PCI info to im_dummy driver --- src/im_mad/dummy/one_im_dummy.rb | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/im_mad/dummy/one_im_dummy.rb b/src/im_mad/dummy/one_im_dummy.rb index fa141c9c46..0686dfd331 100755 --- a/src/im_mad/dummy/one_im_dummy.rb +++ b/src/im_mad/dummy/one_im_dummy.rb @@ -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) From 991b67197d60504868d53e0a69edc057ddb80088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 26 Aug 2015 11:05:51 +0200 Subject: [PATCH 17/18] Feature #3028: Fix sched log formatting --- src/scheduler/src/pool/VirtualMachinePoolXML.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scheduler/src/pool/VirtualMachinePoolXML.cc b/src/scheduler/src/pool/VirtualMachinePoolXML.cc index 319b207f29..e4acb9f0f2 100644 --- a/src/scheduler/src/pool/VirtualMachinePoolXML.cc +++ b/src/scheduler/src/pool/VirtualMachinePoolXML.cc @@ -39,7 +39,7 @@ int VirtualMachinePoolXML::set_up() << right << setw(8) << "VM" << " " << right << setw(4) << "CPU" << " " << right << setw(11) << "Memory" << " " - << right << setw(2) << "PCI" << " " + << right << setw(3) << "PCI" << " " << right << setw(11) << "System DS" << " " << " Image DS" << endl << setw(60) << setfill('-') << "-" << setfill(' '); @@ -70,7 +70,7 @@ int VirtualMachinePoolXML::set_up() << right << setw(8) << it->first << " " << right << setw(4) << cpu << " " << right << setw(11) << mem << " " - << right << setw(2) << pci.size() << " " + << right << setw(3) << pci.size() << " " << right << setw(11) << disk << " "; map ds_usage = vm->get_storage_usage(); From e348918ea20edb58ca5f5383899ab878023f0e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn?= Date: Wed, 26 Aug 2015 12:34:27 +0200 Subject: [PATCH 18/18] Feature #3028: Check pci devices in Host::test_capacity --- include/Host.h | 7 ++- include/HostShare.h | 69 ++++++++++++++++------ include/RequestManagerVirtualMachine.h | 7 +-- src/host/HostShare.cc | 66 ++++++++++++++++++++- src/rm/RequestManagerVirtualMachine.cc | 81 ++++++++++++-------------- src/scheduler/include/HostXML.h | 4 +- src/vm/VirtualMachine.cc | 4 +- 7 files changed, 163 insertions(+), 75 deletions(-) diff --git a/include/Host.h b/include/Host.h index b715b985b4..7874680348 100644 --- a/include/Host.h +++ b/include/Host.h @@ -444,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 &pci, string& error) { - return host_share.test(cpu, mem, disk); + return host_share.test(cpu, mem, disk, pci, error); } /** diff --git a/include/HostShare.h b/include/HostShare.h index e62907f1eb..c980ab97f2 100644 --- a/include/HostShare.h +++ b/include/HostShare.h @@ -75,21 +75,18 @@ public: int from_xml_node(const xmlNodePtr node); /** - * Test wether this PCI device set has the requested devices available. + * 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 &devs) - { - return test_set(devs, -1); - } + bool test(vector &devs) const; /** - * Assign the requested devices to the given VM. The assgined devices will + * 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 - * assgined devices. + * assigned devices. * @param vmid of the VM */ void add(vector &devs, int vmid) @@ -98,7 +95,7 @@ public: } /** - * Remove the VM assigment from the PCI device list + * Remove the VM assignment from the PCI device list */ void del(const vector &devs); @@ -122,30 +119,48 @@ private: /** * Test if a PCIDevice matches the vendor, device and class request spec - * and can be assigned. It will assgin it if requested. + * 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 assgined set of addresses already assgined devices, it will + * @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 &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 &assigned); + std::set &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 assgined. + * @return true if the PCIDevice list can be assigned. */ - bool test_set(vector &devs, int vmid); + bool test_set(vector &devs, int vmid) const; /** * Gets a 4 hex digits value from attribute @@ -249,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& 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; } /** diff --git a/include/RequestManagerVirtualMachine.h b/include/RequestManagerVirtualMachine.h index 0455ec12d3..cac7729196 100644 --- a/include/RequestManagerVirtualMachine.h +++ b/include/RequestManagerVirtualMachine.h @@ -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, diff --git a/src/host/HostShare.cc b/src/host/HostShare.cc index 130b32b6bd..f511a7bcba 100644 --- a/src/host/HostShare.cc +++ b/src/host/HostShare.cc @@ -64,14 +64,74 @@ int HostSharePCI::init() return 0; } +/* ------------------------------------------------------------------------*/ +/* ------------------------------------------------------------------------*/ + +bool HostSharePCI::test(unsigned int vendor_id, unsigned int device_id, + unsigned int class_id, const VectorAttribute * devreq, + std::set& assigned) const +{ + map::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 &devs) const +{ + vector::iterator it; + std::set assigned; + + unsigned int vendor_id, device_id, class_id; + + for ( it=devs.begin(); it!= devs.end(); it++) + { + VectorAttribute * pci = dynamic_cast(*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& assigned) + std::set& assigned) const { - map::iterator it; + map::const_iterator it; for (it=pci_devices.begin(); it!=pci_devices.end(); it++) { @@ -107,7 +167,7 @@ bool HostSharePCI::test_set(unsigned int vendor_id, unsigned int device_id, /* ------------------------------------------------------------------------*/ -bool HostSharePCI::test_set(vector &devs, int vmid) +bool HostSharePCI::test_set(vector &devs, int vmid) const { vector::iterator it; std::set assigned; diff --git a/src/rm/RequestManagerVirtualMachine.cc b/src/rm/RequestManagerVirtualMachine.cc index de716596a6..406e948e6e 100644 --- a/src/rm/RequestManagerVirtualMachine.cc +++ b/src/rm/RequestManagerVirtualMachine.cc @@ -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 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,27 +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; - vector pci; - - string error; - - vm->get_requirements(cpu, mem, disk, pci); - 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; } // ------------------------------------------------------------------------ @@ -899,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 // ------------------------------------------------------------------------ @@ -1033,28 +1033,16 @@ void VirtualMachineMigrate::request_execute(xmlrpc_c::paramList const& paramList } // Check the host has enough capacity - if (enforce) - { - int cpu, mem, disk; - vector pci; - - string error; - - vm->get_requirements(cpu, mem, disk, pci); - - 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); @@ -1835,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 empty_pci; + string error; + host = hpool->get(hid, true); if (host == 0) @@ -1848,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; diff --git a/src/scheduler/include/HostXML.h b/src/scheduler/include/HostXML.h index 15576ac6f7..ec60fb484a 100644 --- a/src/scheduler/include/HostXML.h +++ b/src/scheduler/include/HostXML.h @@ -51,7 +51,7 @@ 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 byt the VM + * @param pci devices needed by the VM * @param error error message * @return true if the share can host the VM */ @@ -62,7 +62,7 @@ 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 byt the VM + * @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,vector &p) diff --git a/src/vm/VirtualMachine.cc b/src/vm/VirtualMachine.cc index 8f738cdb58..1169314632 100644 --- a/src/vm/VirtualMachine.cc +++ b/src/vm/VirtualMachine.cc @@ -1679,8 +1679,6 @@ void VirtualMachine::get_requirements (int& cpu, int& memory, int& disk, pci_devs.clear(); - obj_template->get("PCI", pci_devs); - if ((get_template_attribute("MEMORY",memory) == false) || (get_template_attribute("CPU",fcpu) == false)) { @@ -1695,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; }