diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 68dce7255a..0b176c97ee 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -723,6 +723,14 @@ public: to_xml_extended(history->vm_info, 0); }; + /** + * Gets end time of a VM + */ + time_t get_etime() + { + return history->etime; + } + /** * Sets end time of a VM in the previous Host. It also sets the vm_info * when the record is closed @@ -779,6 +787,14 @@ public: history->running_etime = _etime; }; + /** + * Gets the running end time for the VM + */ + time_t get_running_etime() const + { + return history->running_etime; + } + /** * Sets end time of VM running state in the previous host. * @param _etime time when the running state finished diff --git a/include/VirtualMachinePool.h b/include/VirtualMachinePool.h index e56d1472d0..a61e2a1279 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -36,7 +36,8 @@ public: bool on_hold, float default_cpu_cost, float default_mem_cost, - float default_disk_cost); + float default_disk_cost, + bool showback_only_running); ~VirtualMachinePool(){}; @@ -431,6 +432,15 @@ private: float _default_mem_cost; float _default_disk_cost; + /** + * Switch for showback cpu and memory cost calculation + * - true: count only running VMs for CPU and MEMORY + * - false: include reservations for CPU and MEMORY + * this includes poweroff and suspended VM states + * note: datastore cost is always counted in poweroff and suspended state + */ + bool _showback_only_running; + /** * Callback used to get an int in the DB it is used by VM Pool in: * - calculate_showback (min_stime) diff --git a/share/etc/oned.conf b/share/etc/oned.conf index 602ee1c252..a90cbaa3e5 100644 --- a/share/etc/oned.conf +++ b/share/etc/oned.conf @@ -207,6 +207,11 @@ DEFAULT_COST = [ DISK_COST = 0 ] +# Should showback calculation count only running VMs. +# If 'no' showback will inlcude also reserved CPU and MEMORY, e.g. VM states +# POWEROFF or SUSPENDED +SHOWBACK_ONLY_RUNNING = "no" + #******************************************************************************* # XML-RPC server configuration #------------------------------------------------------------------------------- diff --git a/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index 40a04f8d8e..8001a901de 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1299,8 +1299,16 @@ static void close_cp_history(VirtualMachinePool *vmpool, VirtualMachine *vm, VMActions::Action action, const RequestAttributes& ra) { time_t the_time = time(0); + bool set_retime = false; - vm->set_running_etime(the_time); + if (vm->get_running_etime() == 0) + { + vm->set_running_etime(the_time); + } + else + { + set_retime = true; + } vm->set_etime(the_time); @@ -1318,6 +1326,11 @@ static void close_cp_history(VirtualMachinePool *vmpool, VirtualMachine *vm, vm->set_running_stime(the_time); + if (set_retime) //Keep VM not running + { + vm->set_running_etime(the_time); + } + vmpool->insert_history(vm); } @@ -1743,7 +1756,14 @@ int DispatchManager::attach_nic(int vid, VirtualMachineTemplate* tmpl, vm->log("DiM", Log::INFO, "VM NIC Successfully attached."); vm->clear_attach_nic(); + vmpool->update_search(vm.get()); + + time_t the_time = time(0); + + vm->set_running_etime(the_time); + + vmpool->update_history(vm.get()); } vmpool->update(vm.get()); diff --git a/src/dm/DispatchManagerStates.cc b/src/dm/DispatchManagerStates.cc index d85ee31778..e73a2eb920 100644 --- a/src/dm/DispatchManagerStates.cc +++ b/src/dm/DispatchManagerStates.cc @@ -49,6 +49,12 @@ void DispatchManager::trigger_suspend_success(int vid) vm->set_state(VirtualMachine::LCM_INIT); + time_t the_time = time(0); + + vm->set_running_etime(the_time); + + vmpool->update_history(vm.get()); + vmpool->update(vm.get()); int uid = vm->get_uid(); @@ -216,6 +222,12 @@ void DispatchManager::trigger_poweroff_success(int vid) vm->set_state(VirtualMachine::LCM_INIT); + time_t the_time = time(0); + + vm->set_running_etime(the_time); + + vmpool->update_history(vm.get()); + vmpool->update(vm.get()); int uid = vm->get_uid(); diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index e33e3fa037..8bae510d82 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -751,8 +751,6 @@ void LifeCycleManager::trigger_restore(int vid, const RequestAttributes& ra) vm->set_etime(the_time); - vm->set_running_etime(the_time); - vmpool->update_history(vm.get()); vm->cp_history(); @@ -814,8 +812,6 @@ void LifeCycleManager::trigger_restart(int vid, const RequestAttributes& ra) vm->set_etime(the_time); - vm->set_running_etime(the_time); - vmpool->update_history(vm.get()); vm->cp_history(); @@ -1006,7 +1002,10 @@ void LifeCycleManager::clean_up_vm(VirtualMachine * vm, bool dispose, vm->delete_snapshots(); } - vm->set_etime(the_time); + if (vm->get_etime() == 0) + { + vm->set_etime(the_time); + } vm->get_capacity(sr); diff --git a/src/lcm/LifeCycleStates.cc b/src/lcm/LifeCycleStates.cc index 22dabe9543..5686b1a407 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -304,20 +304,14 @@ void LifeCycleManager::trigger_deploy_success(int vid) vm->get_lcm_state() == VirtualMachine::BOOT_UNDEPLOY_FAILURE || vm->get_lcm_state() == VirtualMachine::BOOT_FAILURE ) { - if ( vm->get_lcm_state() == VirtualMachine::BOOT_SUSPENDED || - vm->get_lcm_state() == VirtualMachine::BOOT_POWEROFF ) - { - vm->set_previous_etime(time(0)); - - vm->set_previous_running_etime(time(0)); - - vmpool->update_previous_history(vm.get()); - } - vm->set_state(VirtualMachine::RUNNING); vm->clear_action(); + vm->set_etime(0); + + vm->set_running_etime(0); + vmpool->update_history(vm.get()); vmpool->update(vm.get()); @@ -342,12 +336,12 @@ void LifeCycleManager::trigger_deploy_failure(int vid) return; } + time_t the_time = time(0); + if ( vm->get_lcm_state() == VirtualMachine::MIGRATE ) { HostShareCapacity sr; - time_t the_time = time(0); - //---------------------------------------------------- // RUNNING STATE FROM MIGRATE //---------------------------------------------------- @@ -384,50 +378,42 @@ void LifeCycleManager::trigger_deploy_failure(int vid) vm->log("LCM", Log::INFO, "Fail to live migrate VM." " Assuming that the VM is still RUNNING."); + + return; } else if (vm->get_lcm_state() == VirtualMachine::BOOT) { vm->set_state(VirtualMachine::BOOT_FAILURE); - - vmpool->update(vm.get()); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_MIGRATE) { vm->set_state(VirtualMachine::BOOT_MIGRATE_FAILURE); - - vmpool->update(vm.get()); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_UNKNOWN) { vm->set_state(VirtualMachine::UNKNOWN); - - vmpool->update(vm.get()); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_POWEROFF) { vm->set_state(VirtualMachine::POWEROFF); vm->set_state(VirtualMachine::LCM_INIT); - - vmpool->update(vm.get()); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_SUSPENDED) { vm->set_state(VirtualMachine::SUSPENDED); vm->set_state(VirtualMachine::LCM_INIT); - - vmpool->update(vm.get()); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_STOPPED) { vm->set_state(VirtualMachine::BOOT_STOPPED_FAILURE); - vmpool->update(vm.get()); + vm->set_etime(the_time); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_UNDEPLOY) { vm->set_state(VirtualMachine::BOOT_UNDEPLOY_FAILURE); - vmpool->update(vm.get()); + vm->set_etime(the_time); } //wrong state + recover failure from failure state else if ( vm->get_lcm_state() != VirtualMachine::BOOT_FAILURE && @@ -437,6 +423,12 @@ void LifeCycleManager::trigger_deploy_failure(int vid) { vm->log("LCM",Log::ERROR,"deploy_failure_action, VM in a wrong state"); } + + vm->set_running_etime(the_time); + + vmpool->update_history(vm.get()); + + vmpool->update(vm.get()); }); } diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index d4d95688c9..1ef8ea34bc 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -660,6 +660,7 @@ void Nebula::start(bool bootstrap_only) float cpu_cost; float mem_cost; float disk_cost; + bool showback_only_running; const VectorAttribute * default_cost; @@ -686,8 +687,10 @@ void Nebula::start(bool bootstrap_only) disk_cost = 0; } + nebula_configuration->get("SHOWBACK_ONLY_RUNNING", showback_only_running); + vmpool = new VirtualMachinePool(logdb, vm_restricted_attrs, vm_encrypted_attrs, - vm_submit_on_hold, cpu_cost, mem_cost, disk_cost); + vm_submit_on_hold, cpu_cost, mem_cost, disk_cost, showback_only_running); /* ---------------------------- Host Pool --------------------------- */ vector host_encrypted_attrs; diff --git a/src/template/OpenNebulaTemplate.cc b/src/template/OpenNebulaTemplate.cc index 23f23bf727..b011b4d252 100644 --- a/src/template/OpenNebulaTemplate.cc +++ b/src/template/OpenNebulaTemplate.cc @@ -362,6 +362,7 @@ void OpenNebulaTemplate::set_conf_default() # VM_SUBMIT_ON_HOLD # API_LIST_ORDER # VNC_PORTS +# SHOWBACK_ONLY_RUNNING #******************************************************************************* */ set_conf_single("MANAGER_TIMER", "15"); @@ -382,7 +383,7 @@ void OpenNebulaTemplate::set_conf_default() set_conf_single("HOST_ENCRYPTED_ATTR", "VCENTER_PASSWORD"); set_conf_single("HOST_ENCRYPTED_ATTR", "NSX_PASSWORD"); set_conf_single("HOST_ENCRYPTED_ATTR", "ONE_PASSWORD"); - + set_conf_single("SHOWBACK_ONLY_RUNNING", "NO"); //DB CONFIGURATION vvalue.insert(make_pair("BACKEND","sqlite")); diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 80c4897bd3..45251e9d5b 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -36,11 +36,13 @@ VirtualMachinePool::VirtualMachinePool( bool on_hold, float default_cpu_cost, float default_mem_cost, - float default_disk_cost) + float default_disk_cost, + bool showback_only_running) : PoolSQL(db, one_db::vm_table), _submit_on_hold(on_hold), _default_cpu_cost(default_cpu_cost), _default_mem_cost(default_mem_cost), - _default_disk_cost(default_disk_cost) + _default_disk_cost(default_disk_cost), + _showback_only_running(showback_only_running) { // Set restricted attributes VirtualMachineTemplate::parse_restricted(restricted_attrs); @@ -575,8 +577,8 @@ int VirtualMachinePool::calculate_showback( tm tmp_tm; int vid; - int h_stime; - int h_etime; + time_t h_stime, h_rstime; + time_t h_etime, h_retime; float cpu_cost; float mem_cost; float disk_cost; @@ -719,8 +721,11 @@ int VirtualMachinePool::calculate_showback( history.xpath(vid, "/HISTORY/OID", -1); - history.xpath(h_stime, "/HISTORY/STIME", 0); - history.xpath(h_etime, "/HISTORY/ETIME", 0); + history.xpath(h_stime, "/HISTORY/STIME", (time_t)0); + history.xpath(h_etime, "/HISTORY/ETIME", (time_t)0); + + history.xpath(h_rstime, "/HISTORY/RSTIME", (time_t)0); + history.xpath(h_retime, "/HISTORY/RETIME", (time_t)0); history.xpath(cpu, "/HISTORY/VM/TEMPLATE/CPU", 0.0); history.xpath(mem, "/HISTORY/VM/TEMPLATE/MEMORY", 0); @@ -761,28 +766,47 @@ int VirtualMachinePool::calculate_showback( time_t t = *slot_it; time_t t_next = *(slot_it+1); - if( (h_etime > t || h_etime == 0) && - (h_stime != 0 && h_stime <= t_next) ) { + auto count_sb_record = [&](time_t st, time_t et, bool cpu_mem, bool disk_total) + { + if( (et > t || et == 0) && + (st != 0 && st <= t_next) ) { - time_t stime = t; - if(h_stime != 0){ - stime = (t < h_stime) ? h_stime : t; //max(t, h_stime); + time_t stime = t; + if(st != 0){ + stime = max(t, st); + } + + time_t etime = t_next; + if(et != 0){ + etime = min(t_next, et); + } + + float n_hours = difftime(etime, stime) / 60 / 60; + + // Add to vm time slot. + SBRecord& totals = vm_cost.totals[t]; + + if (cpu_mem) + { + totals.cpu_cost += cpu_cost * cpu * n_hours; + totals.mem_cost += mem_cost * mem * n_hours; + } + if (disk_total) + { + totals.disk_cost+= disk_cost* disk* n_hours; + totals.hours += n_hours; + } } + }; - time_t etime = t_next; - if(h_etime != 0){ - etime = (t_next < h_etime) ? t_next : h_etime; //min(t_next, h_etime); - } - - float n_hours = difftime(etime, stime) / 60 / 60; - - // Add to vm time slot. - SBRecord& totals = vm_cost.totals[t]; - - totals.cpu_cost += cpu_cost * cpu * n_hours; - totals.mem_cost += mem_cost * mem * n_hours; - totals.disk_cost+= disk_cost* disk* n_hours; - totals.hours += n_hours; + if (_showback_only_running) + { + count_sb_record(h_stime, h_etime, false, true); + count_sb_record(h_rstime, h_retime, true, false); + } + else + { + count_sb_record(h_stime, h_etime, true, true); } } }