diff --git a/src/scheduler/include/DatastoreXML.h b/src/scheduler/include/DatastoreXML.h index b31b93261e..97eb15e122 100644 --- a/src/scheduler/include/DatastoreXML.h +++ b/src/scheduler/include/DatastoreXML.h @@ -36,14 +36,23 @@ public: }; /** - * Tests whether a new VM can be hosted by the datasotre + * Tests whether a new VM can be hosted by the datastore + * @param vm_disk_mb capacity needed by the VM + * @param error error message + * @return true if the datastore can host the VM + */ + bool test_capacity(long long vm_disk_mb, string & error) const; + + /** + * Tests whether a new VM can be hosted by the datastore * @param vm_disk_mb capacity needed by the VM * @return true if the datastore can host the VM */ bool test_capacity(long long vm_disk_mb) const { - return (vm_disk_mb < free_mb); - }; + string tmp_st; + return test_capacity(vm_disk_mb, tmp_st); + } /** * Adds a new VM to the datastore diff --git a/src/scheduler/include/HostXML.h b/src/scheduler/include/HostXML.h index 17f121d61a..fb9cb2504d 100644 --- a/src/scheduler/include/HostXML.h +++ b/src/scheduler/include/HostXML.h @@ -46,6 +46,15 @@ public: return cluster_id; }; + /** + * 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 error error message + * @return true if the share can host the VM + */ + bool test_capacity(long long cpu, long long mem, string & error) const; + /** * Tests whether a new VM can be hosted by the host or not * @param cpu needed by the VM (percentage) @@ -54,8 +63,8 @@ public: */ bool test_capacity(long long cpu, long long mem) const { - return (((max_cpu - cpu_usage ) >= cpu) && - ((max_mem - mem_usage ) >= mem)); + string tmp_st; + return test_capacity(cpu, mem, tmp_st); }; /** diff --git a/src/scheduler/include/VirtualMachineXML.h b/src/scheduler/include/VirtualMachineXML.h index bec5b0caf4..7a827da1ae 100644 --- a/src/scheduler/include/VirtualMachineXML.h +++ b/src/scheduler/include/VirtualMachineXML.h @@ -215,9 +215,23 @@ public: /** * Tests if the Image DS have enough free space to host the VM * @param img_datastores Image Datastores + * @param error_msg error reason * @return true if the Image Datastores can host the VM */ - bool test_image_datastore_capacity(ImageDatastorePoolXML * img_dspool); + bool test_image_datastore_capacity( + ImageDatastorePoolXML * img_dspool, string & error_msg) const; + + /** + * Tests if the Image DS have enough free space to host the VM + * @param img_datastores Image Datastores + * @return true if the Image Datastores can host the VM + */ + bool test_image_datastore_capacity( + ImageDatastorePoolXML * img_dspool) const + { + string tmp_st; + return test_image_datastore_capacity(img_dspool, tmp_st); + } /** * Adds the VM disk requirements to each Image Datastore counter diff --git a/src/scheduler/src/pool/DatastoreXML.cc b/src/scheduler/src/pool/DatastoreXML.cc index 145998be6f..ddb76835b6 100644 --- a/src/scheduler/src/pool/DatastoreXML.cc +++ b/src/scheduler/src/pool/DatastoreXML.cc @@ -18,6 +18,7 @@ #include "DatastoreXML.h" #include "NebulaUtil.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -71,3 +72,31 @@ void DatastoreXML::init_attributes() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ + +bool DatastoreXML::test_capacity(long long vm_disk_mb, string & error) const +{ + bool fits = (vm_disk_mb < free_mb) || (vm_disk_mb == 0); + + if (!fits) + { + if (NebulaLog::log_level() >= Log::DDEBUG) + { + ostringstream oss; + + oss << "Not enough capacity. " + << "Requested: " << vm_disk_mb << " MB, " + << "Available: " << free_mb << " MB"; + + error = oss.str(); + } + else + { + error = "Not enough capacity."; + } + } + + return fits; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ diff --git a/src/scheduler/src/pool/HostXML.cc b/src/scheduler/src/pool/HostXML.cc index f8182cd0fc..e32b8fc4c0 100644 --- a/src/scheduler/src/pool/HostXML.cc +++ b/src/scheduler/src/pool/HostXML.cc @@ -19,6 +19,7 @@ #include "HostXML.h" #include "NebulaUtil.h" +#include "NebulaLog.h" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ @@ -122,6 +123,39 @@ int HostXML::search(const char *name, int& value) /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +bool HostXML::test_capacity(long long cpu, long long mem, string & error) const +{ + bool fits = (((max_cpu - cpu_usage ) >= cpu) && + ((max_mem - mem_usage ) >= mem)); + + if (!fits) + { + if (NebulaLog::log_level() >= Log::DDEBUG) + { + ostringstream oss; + + 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(); + } + else + { + error = "Not enough capacity."; + } + } + + return fits; +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + bool HostXML::test_ds_capacity(int dsid, long long vm_disk_mb) { if (ds_free_disk.count(dsid) == 0) diff --git a/src/scheduler/src/pool/VirtualMachineXML.cc b/src/scheduler/src/pool/VirtualMachineXML.cc index 4d80a8725e..5e7a8b6dec 100644 --- a/src/scheduler/src/pool/VirtualMachineXML.cc +++ b/src/scheduler/src/pool/VirtualMachineXML.cc @@ -455,7 +455,7 @@ int VirtualMachineXML::parse_action_name(string& action_st) /* -------------------------------------------------------------------------- */ bool VirtualMachineXML::test_image_datastore_capacity( - ImageDatastorePoolXML * img_dspool) + ImageDatastorePoolXML * img_dspool, string & error_msg) const { map::const_iterator ds_usage_it; DatastoreXML* ds; @@ -466,6 +466,12 @@ bool VirtualMachineXML::test_image_datastore_capacity( if (ds == 0 || !ds->test_capacity(ds_usage_it->second)) { + ostringstream oss; + + oss << "Image Datastore " << ds->get_oid() + << " does not have enough capacity"; + + error_msg = oss.str(); return false; } } diff --git a/src/scheduler/src/sched/Scheduler.cc b/src/scheduler/src/sched/Scheduler.cc index 24ad5c6337..4c4bb634ce 100644 --- a/src/scheduler/src/sched/Scheduler.cc +++ b/src/scheduler/src/sched/Scheduler.cc @@ -560,9 +560,8 @@ static bool match_host(AclXML * acls, VirtualMachineXML* vm, int vmem, int vcpu, // ------------------------------------------------------------------------- // Check host capacity // ------------------------------------------------------------------------- - if (host->test_capacity(vcpu,vmem) != true) + if (host->test_capacity(vcpu,vmem,error) != true) { - error = "Not enough capacity."; return false; } @@ -628,18 +627,6 @@ static bool match_system_ds(AclXML * acls, VirtualMachineXML* vm, long long vdis DatastoreXML * ds, int& n_auth, int& n_error, int& n_fits, int &n_matched, string &error) { - // ------------------------------------------------------------------------- - // Check datastore capacity for shared systems DS (non-shared will be - // checked in a per host basis during dispatch) - // ------------------------------------------------------------------------- - if (ds->is_shared() && ds->is_monitored() && !ds->test_capacity(vdisk)) - { - error = "Not enough capacity."; - return false; - } - - n_fits++; - // ------------------------------------------------------------------------- // Check if user is authorized // ------------------------------------------------------------------------- @@ -665,6 +652,17 @@ static bool match_system_ds(AclXML * acls, VirtualMachineXML* vm, long long vdis n_auth++; + // ------------------------------------------------------------------------- + // Check datastore capacity for shared systems DS (non-shared will be + // checked in a per host basis during dispatch) + // ------------------------------------------------------------------------- + if (ds->is_shared() && ds->is_monitored() && !ds->test_capacity(vdisk, error)) + { + return false; + } + + n_fits++; + // ------------------------------------------------------------------------- // Evaluate VM requirements // ------------------------------------------------------------------------- @@ -763,7 +761,7 @@ void Scheduler::match_schedule() //---------------------------------------------------------------------- if (!vm->is_resched()) { - if (vm->test_image_datastore_capacity(img_dspool) == false) + if (vm->test_image_datastore_capacity(img_dspool, m_error) == false) { if (vm->is_public_cloud()) //No capacity needed for public cloud { @@ -771,8 +769,11 @@ void Scheduler::match_schedule() } else { - log_match(vm->get_oid(), "Cannot schedule VM, image datastore " - "does not have enough capacity."); + log_match(vm->get_oid(), "Cannot schedule VM. "+m_error); + + vm->log("Cannot schedule VM. "+m_error); + vmpool->update(vm); + continue; } } @@ -794,10 +795,21 @@ void Scheduler::match_schedule() n_resources++; } - else if ( n_error > 0 ) + else { - log_match(vm->get_oid(), "Cannot schedule VM. " + m_error); - break; + if ( n_error > 0 ) + { + log_match(vm->get_oid(), "Cannot schedule VM. " + m_error); + break; + } + else if (NebulaLog::log_level() >= Log::DDEBUG) + { + ostringstream oss; + oss << "Host " << host->get_hid() << " discarded for VM " + << vm->get_oid() << ". " << m_error; + + NebulaLog::log("SCHED", Log::DDEBUG, oss); + } } } @@ -819,19 +831,23 @@ void Scheduler::match_schedule() { vm->log("User is not authorized to use any host"); } + else if (n_fits == 0) + { + ostringstream oss; + + oss << "No host with enough capacity to deploy the VM"; + + vm->log(oss.str()); + } else if (n_matched == 0) { ostringstream oss; - oss << "No host meets SCHED_REQUIREMENTS: " + oss << "No host meets capacity and SCHED_REQUIREMENTS: " << vm->get_requirements(); vm->log(oss.str()); } - else if (n_fits == 0) - { - vm->log("No host with enough capacity to deploy the VM"); - } } vmpool->update(vm); @@ -883,10 +899,21 @@ void Scheduler::match_schedule() n_resources++; } - else if (n_error > 0) + else { - log_match(vm->get_oid(), "Cannot schedule VM. " + m_error); - break; + if (n_error > 0) + { + log_match(vm->get_oid(), "Cannot schedule VM. " + m_error); + break; + } + else if (NebulaLog::log_level() >= Log::DDEBUG) + { + ostringstream oss; + oss << "System DS " << ds->get_oid() << " discarded for VM " + << vm->get_oid() << ". " << m_error; + + NebulaLog::log("SCHED", Log::DDEBUG, oss); + } } } @@ -910,22 +937,26 @@ void Scheduler::match_schedule() { vm->log("No system datastores found to run VMs"); } - else if (n_matched == 0) - { - ostringstream oss; - - oss << "No system datastore meets SCHED_DS_REQUIREMENTS: " - << vm->get_ds_requirements(); - - vm->log(oss.str()); - } else if (n_auth == 0) { vm->log("User is not authorized to use any system datastore"); } else if (n_fits == 0) { - vm->log("No system datastore with enough capacity for the VM"); + ostringstream oss; + oss << "No system datastore with enough capacity for the VM"; + + vm->log(oss.str()); + } + else if (n_matched == 0) + { + ostringstream oss; + + oss << "No system datastore meets capacity " + << "and SCHED_DS_REQUIREMENTS: " + << vm->get_ds_requirements(); + + vm->log(oss.str()); } }