Revision e348918e

View differences:

include/Host.h
444 444
     *    @param cpu needed by the VM (percentage)
445 445
     *    @param mem needed by the VM (in Kb)
446 446
     *    @param disk needed by the VM
447
     *    @param pci devices needed by the VM
448
     *    @param error Returns the error reason, if any
447 449
     *    @return true if the share can host the VM
448 450
     */
449
    bool test_capacity(long long cpu, long long mem, long long disk)
451
    bool test_capacity(long long cpu, long long mem, long long disk,
452
                       vector<Attribute *> &pci, string& error)
450 453
    {
451
        return host_share.test(cpu, mem, disk);
454
        return host_share.test(cpu, mem, disk, pci, error);
452 455
    }
453 456

  
454 457
    /**
include/HostShare.h
75 75
    int from_xml_node(const xmlNodePtr node);
76 76

  
77 77
    /**
78
     *  Test wether this PCI device set has the requested devices available.
78
     *  Test whether this PCI device set has the requested devices available.
79 79
     *    @param devs list of requested devices by the VM.
80 80
     *    @return true if all the devices are available.
81 81
     */
82
    bool test(vector<Attribute *> &devs)
83
    {
84
        return test_set(devs, -1);
85
    }
82
    bool test(vector<Attribute *> &devs) const;
86 83

  
87 84
    /**
88
     *  Assign the requested devices to the given VM. The assgined devices will
85
     *  Assign the requested devices to the given VM. The assigned devices will
89 86
     *  be labeled with the VM and the PCI attribute of the VM extended with
90 87
     *  the address of the assigned devices.
91 88
     *    @param devs list of requested PCI devices, will include address of
92
    *    assgined devices.
89
     *    assigned devices.
93 90
     *    @param vmid of the VM
94 91
     */
95 92
    void add(vector<Attribute *> &devs, int vmid)
......
98 95
    }
99 96

  
100 97
    /**
101
     *  Remove the VM assigment from the PCI device list
98
     *  Remove the VM assignment from the PCI device list
102 99
     */
103 100
    void del(const vector<Attribute *> &devs);
104 101

  
......
122 119

  
123 120
    /**
124 121
     *  Test if a PCIDevice matches the vendor, device and class request spec
125
     *  and can be assigned. It will assgin it if requested.
122
     *  and can be assigned. If free, it is stored in the assigned set
126 123
     *    @param vendor_id id in uint form 0 means *
127 124
     *    @param device_id id in uint form 0 means *
128 125
     *    @param class_id  id in uint form 0 means *
129 126
     *    @param pci requested pci device
130 127
     *    @param vmid if not -1 it will also assign the PCI device to the VM,
131 128
     *    and the pci attribute will be extended with device information.
132
     *    @param assgined set of addresses already assgined devices, it will
129
     *    @param assigned set of addresses already assigned devices, it will
130
     *    include the  selected device if found; useful to iterate.
131
     *
132
     *    @return true if a device was found.
133
     */
134
    bool test(unsigned int vendor_id, unsigned int device_id,
135
        unsigned int class_id, const VectorAttribute *pci,
136
        std::set<string> &assigned) const;
137

  
138
    /**
139
     *  Test if a PCIDevice matches the vendor, device and class request spec
140
     *  and can be assigned. It will assign it if requested.
141
     *    @param vendor_id id in uint form 0 means *
142
     *    @param device_id id in uint form 0 means *
143
     *    @param class_id  id in uint form 0 means *
144
     *    @param pci requested pci device
145
     *    @param vmid if not -1 it will also assign the PCI device to the VM,
146
     *    and the pci attribute will be extended with device information.
147
     *    @param assigned set of addresses already assigned devices, it will
133 148
     *    include the  selected device if found; useful to iterate.
134 149
     *
135 150
     *    @return true if a device was found.
136 151
     */
137 152
    bool test_set(unsigned int vendor_id, unsigned int device_id,
138 153
        unsigned int class_id, VectorAttribute *pci, int vmid,
139
        std::set<string> &assigned);
154
        std::set<string> &assigned) const;
140 155

  
141 156
    /**
142 157
     *  Test if the given list of PCIDevices can be assigned to the VM
143 158
     *    @param devs, list of PCI devices
144 159
     *    @param vmid if not -1 it will assign the devices to the VM
145 160
     *
146
     *    @return true if the PCIDevice list can be assgined.
161
     *    @return true if the PCIDevice list can be assigned.
147 162
     */
148
    bool test_set(vector<Attribute *> &devs, int vmid);
163
    bool test_set(vector<Attribute *> &devs, int vmid) const;
149 164

  
150 165
    /**
151 166
     *  Gets a 4 hex digits value from attribute
......
249 264
     *    @param cpu requested by the VM
250 265
     *    @param mem requested by the VM
251 266
     *    @param disk requested by the VM
267
     *    @param pci_devs requested by the VM
268
     *    @param error Returns the error reason, if any
252 269
     *
253 270
     *    @return true if the share can host the VM or it is the only one
254 271
     *    configured
255 272
     */
256
    bool test(long long cpu, long long mem, long long disk) const
273
    bool test(long long cpu, long long mem, long long disk,
274
              vector<Attribute *>& pci_devs, string& error) const
257 275
    {
258
            return (((max_cpu  - cpu_usage ) >= cpu) &&
259
                    ((max_mem  - mem_usage ) >= mem) &&
260
                    ((max_disk - disk_usage) >= disk));
276
        bool pci_fits = pci.test(pci_devs);
277

  
278
        bool fits = (((max_cpu  - cpu_usage ) >= cpu) &&
279
                     ((max_mem  - mem_usage ) >= mem) &&
280
                     ((max_disk - disk_usage) >= disk)&&
281
                     pci_fits);
282

  
283
        if (!fits)
284
        {
285
            if ( pci_fits )
286
            {
287
                error = "Not enough capacity.";
288
            }
289
            else
290
            {
291
                error = "Unavailable PCI device.";
292
            }
293
        }
294

  
295
        return fits;
261 296
    }
262 297

  
263 298
    /**
include/RequestManagerVirtualMachine.h
90 90
        string& tm_mad,
91 91
        RequestAttributes& att);
92 92

  
93
    bool check_host(int     hid,
94
                    int     cpu,
95
                    int     mem,
96
                    int     disk,
93
    bool check_host(int hid,
94
                    bool enforce,
95
                    VirtualMachine* vm,
97 96
                    string& error);
98 97

  
99 98
    int add_history(VirtualMachine * vm,
src/host/HostShare.cc
67 67
/* ------------------------------------------------------------------------*/
68 68
/* ------------------------------------------------------------------------*/
69 69

  
70
bool HostSharePCI::test(unsigned int vendor_id, unsigned int device_id,
71
        unsigned int class_id, const VectorAttribute * devreq,
72
        std::set<string>& assigned) const
73
{
74
    map<string, PCIDevice *>::const_iterator it;
75

  
76
    for (it=pci_devices.begin(); it!=pci_devices.end(); it++)
77
    {
78
        PCIDevice * dev = it->second;
79

  
80
        if ((class_id  == 0 || dev->class_id  == class_id)  &&
81
            (vendor_id == 0 || dev->vendor_id == vendor_id) &&
82
            (device_id == 0 || dev->device_id == device_id) &&
83
            dev->vmid  == -1 &&
84
            assigned.find(dev->address) == assigned.end())
85
        {
86
            assigned.insert(dev->address);
87

  
88
            return true;
89
        }
90
    }
91

  
92
    return false;
93
}
94

  
95
/* ------------------------------------------------------------------------*/
96

  
97
bool HostSharePCI::test(vector<Attribute *> &devs) const
98
{
99
    vector<Attribute *>::iterator it;
100
    std::set<string> assigned;
101

  
102
    unsigned int vendor_id, device_id, class_id;
103

  
104
    for ( it=devs.begin(); it!= devs.end(); it++)
105
    {
106
        VectorAttribute * pci = dynamic_cast<VectorAttribute *>(*it);
107

  
108
        if ( pci == 0 )
109
        {
110
            return false;
111
        }
112

  
113
        vendor_id = get_pci_value("VENDOR", pci);
114
        device_id = get_pci_value("DEVICE", pci);
115
        class_id  = get_pci_value("CLASS", pci);
116

  
117
        if (!test(vendor_id, device_id, class_id, pci, assigned))
118
        {
119
            return false;
120
        }
121
    }
122

  
123
    return true;
124
}
125

  
126

  
127
/* ------------------------------------------------------------------------*/
128
/* ------------------------------------------------------------------------*/
129

  
70 130
bool HostSharePCI::test_set(unsigned int vendor_id, unsigned int device_id,
71 131
        unsigned int class_id, VectorAttribute * devreq, int vmid,
72
        std::set<string>& assigned)
132
        std::set<string>& assigned) const
73 133
{
74
    map<string, PCIDevice *>::iterator it;
134
    map<string, PCIDevice *>::const_iterator it;
75 135

  
76 136
    for (it=pci_devices.begin(); it!=pci_devices.end(); it++)
77 137
    {
......
107 167

  
108 168
/* ------------------------------------------------------------------------*/
109 169

  
110
bool HostSharePCI::test_set(vector<Attribute *> &devs, int vmid)
170
bool HostSharePCI::test_set(vector<Attribute *> &devs, int vmid) const
111 171
{
112 172
    vector<Attribute *>::iterator it;
113 173
    std::set<string> assigned;
src/rm/RequestManagerVirtualMachine.cc
375 375
/* -------------------------------------------------------------------------- */
376 376
/* -------------------------------------------------------------------------- */
377 377

  
378
bool RequestManagerVirtualMachine::check_host(int     hid,
379
                                              int     cpu,
380
                                              int     mem,
381
                                              int     disk,
382
                                              string& error)
378
bool RequestManagerVirtualMachine::check_host(
379
        int hid, bool enforce, VirtualMachine* vm, string& error)
383 380
{
384 381
    Nebula&    nd    = Nebula::instance();
385 382
    HostPool * hpool = nd.get_hpool();
386 383

  
387 384
    Host * host;
388 385
    bool   test;
386
    string capacity_error;
387

  
388
    int cpu, mem, disk;
389
    vector<Attribute *> pci;
390

  
391
    vm->get_requirements(cpu, mem, disk, pci);
389 392

  
390 393
    host = hpool->get(hid, true);
391 394

  
......
395 398
        return false;
396 399
    }
397 400

  
398
    test = host->test_capacity(cpu, mem, disk);
401
    if (!enforce)
402
    {
403
        cpu  = 0;
404
        mem  = 0;
405
        disk = 0;
406
    }
407

  
408
    test = host->test_capacity(cpu, mem, disk, pci, capacity_error);
399 409

  
400 410
    if (!test)
401 411
    {
402 412
        ostringstream oss;
403 413

  
404
        oss << object_name(PoolObjectSQL::HOST)
405
            << " " << hid << " does not have enough capacity.";
414
        oss << object_name(PoolObjectSQL::VM) << " [" << vm->get_oid()
415
            << "] does not fit in " << object_name(PoolObjectSQL::HOST)
416
            << " [" << hid << "]. " << capacity_error;
406 417

  
407 418
        error = oss.str();
408 419
    }
......
662 673

  
663 674
    bool auth = false;
664 675

  
676
    string error;
677

  
665 678
    // ------------------------------------------------------------------------
666 679
    // Get request parameters and information about the target host
667 680
    // ------------------------------------------------------------------------
......
814 827
        return;
815 828
    }
816 829

  
817
    if (enforce)
830
    if (check_host(hid, enforce, vm, error) == false)
818 831
    {
819
        int cpu, mem, disk;
820
        vector<Attribute *> pci;
821

  
822
        string error;
823

  
824
        vm->get_requirements(cpu, mem, disk, pci);
825

  
826 832
        vm->unlock();
827 833

  
828
        if (check_host(hid, cpu, mem, disk, error) == false)
829
        {
830
            failure_response(ACTION, request_error(error,""), att);
831
            return;
832
        }
833

  
834
        if ((vm = get_vm(id, att)) == 0)
835
        {
836
            return;
837
        }
834
        failure_response(ACTION, request_error(error,""), att);
835
        return;
838 836
    }
839 837

  
840 838
    // ------------------------------------------------------------------------
......
899 897

  
900 898
    bool auth = false;
901 899

  
900
    string error;
901

  
902 902
    // ------------------------------------------------------------------------
903 903
    // Get request parameters and information about the target host
904 904
    // ------------------------------------------------------------------------
......
1033 1033
    }
1034 1034

  
1035 1035
    // Check the host has enough capacity
1036
    if (enforce)
1036
    if (check_host(hid, enforce, vm, error) == false)
1037 1037
    {
1038
        int cpu, mem, disk;
1039
        vector<Attribute *> pci;
1040

  
1041
        string error;
1042

  
1043
        vm->get_requirements(cpu, mem, disk, pci);
1044

  
1045 1038
        vm->unlock();
1046 1039

  
1047
        if (check_host(hid, cpu, mem, disk, error) == false)
1048
        {
1049
            failure_response(ACTION, request_error(error,""), att);
1050
            return;
1051
        }
1052
    }
1053
    else
1054
    {
1055
        vm->unlock();
1040
        failure_response(ACTION, request_error(error,""), att);
1041
        return;
1056 1042
    }
1057 1043

  
1044
    vm->unlock();
1045

  
1058 1046
    // Check we are in the same cluster
1059 1047
    Host * host = nd.get_hpool()->get(c_hid, true);
1060 1048

  
......
1835 1823
        int dcpu_host = (int) (dcpu * 100);//now in 100%
1836 1824
        int dmem_host = dmemory * 1024;    //now in Kilobytes
1837 1825

  
1826
        vector<Attribute *> empty_pci;
1827
        string error;
1828

  
1838 1829
        host = hpool->get(hid, true);
1839 1830

  
1840 1831
        if (host == 0)
......
1848 1839
            return;
1849 1840
        }
1850 1841

  
1851
        if ( enforce && host->test_capacity(dcpu_host, dmem_host, 0) == false)
1842
        if ( enforce && host->test_capacity(dcpu_host, dmem_host, 0, empty_pci, error) == false)
1852 1843
        {
1853 1844
            ostringstream oss;
1854 1845

  
src/scheduler/include/HostXML.h
51 51
     *  Tests whether a new VM can be hosted by the host or not
52 52
     *    @param cpu needed by the VM (percentage)
53 53
     *    @param mem needed by the VM (in KB)
54
     *    @param pci devices needed byt the VM
54
     *    @param pci devices needed by the VM
55 55
     *    @param error error message
56 56
     *    @return true if the share can host the VM
57 57
     */
......
62 62
     *  Tests whether a new VM can be hosted by the host or not
63 63
     *    @param cpu needed by the VM (percentage)
64 64
     *    @param mem needed by the VM (in KB)
65
     *    @param pci devices needed byt the VM
65
     *    @param pci devices needed by the VM
66 66
     *    @return true if the share can host the VM
67 67
     */
68 68
    bool test_capacity(long long cpu,long long mem,vector<Attribute *> &p)
src/vm/VirtualMachine.cc
1679 1679

  
1680 1680
    pci_devs.clear();
1681 1681

  
1682
    obj_template->get("PCI", pci_devs);
1683

  
1684 1682
    if ((get_template_attribute("MEMORY",memory) == false) ||
1685 1683
        (get_template_attribute("CPU",fcpu) == false))
1686 1684
    {
......
1695 1693
    memory = memory * 1024;     //now in Kilobytes
1696 1694
    disk   = 0;
1697 1695

  
1696
    obj_template->get("PCI", pci_devs);
1697

  
1698 1698
    return;
1699 1699
}
1700 1700

  

Also available in: Unified diff