diff --git a/include/VirtualMachine.h b/include/VirtualMachine.h index 01d52a1847..5e84ad6272 100644 --- a/include/VirtualMachine.h +++ b/include/VirtualMachine.h @@ -721,7 +721,16 @@ public: }; /** - * Sets end time of a VM in the previous Host. It also sets the vm_info + * Sets end time of a VM. It also sets the vm_info when the record is closed + * @param _etime time when the VM finished + */ + 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 * @param _etime time when the VM finished */ @@ -776,6 +785,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 cade915df2..88c60b4b9e 100644 --- a/include/VirtualMachinePool.h +++ b/include/VirtualMachinePool.h @@ -38,7 +38,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(){}; @@ -437,6 +438,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/src/dm/DispatchManagerActions.cc b/src/dm/DispatchManagerActions.cc index bd6e46458c..ea8b4efe6b 100644 --- a/src/dm/DispatchManagerActions.cc +++ b/src/dm/DispatchManagerActions.cc @@ -1307,12 +1307,20 @@ int DispatchManager::delete_vm_db(VirtualMachine * vm, /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -static void close_cp_history(VirtualMachinePool *vmpool, VirtualMachine *vm, +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); @@ -1330,6 +1338,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); } @@ -1779,6 +1792,12 @@ int DispatchManager::attach_nic(int vid, VirtualMachineTemplate* tmpl, vm->clear_attach_nic(); vmpool->update_search(vm); + + time_t the_time = time(0); + + vm->set_running_etime(the_time); + + vmpool->update_history(vm); } vmpool->update(vm); diff --git a/src/dm/DispatchManagerStates.cc b/src/dm/DispatchManagerStates.cc index c9af04558d..b07575bb1b 100644 --- a/src/dm/DispatchManagerStates.cc +++ b/src/dm/DispatchManagerStates.cc @@ -48,6 +48,12 @@ void DispatchManager::suspend_success_action(int vid) vm->set_state(VirtualMachine::LCM_INIT); + time_t the_time = time(0); + + vm->set_running_etime(the_time); + + vmpool->update_history(vm); + vmpool->update(vm); } else @@ -231,6 +237,12 @@ void DispatchManager::poweroff_success_action(int vid) vm->set_state(VirtualMachine::LCM_INIT); + time_t the_time = time(0); + + vm->set_running_etime(the_time); + + vmpool->update_history(vm); + vmpool->update(vm); } else diff --git a/src/lcm/LifeCycleActions.cc b/src/lcm/LifeCycleActions.cc index d823cec65a..c0a2cc77b1 100644 --- a/src/lcm/LifeCycleActions.cc +++ b/src/lcm/LifeCycleActions.cc @@ -728,8 +728,6 @@ void LifeCycleManager::restore_action(const LCMAction& la) vm->set_etime(the_time); - vm->set_running_etime(the_time); - vmpool->update_history(vm); vm->cp_history(); @@ -791,8 +789,6 @@ void LifeCycleManager::restart_action(const LCMAction& la) vm->set_etime(the_time); - vm->set_running_etime(the_time); - vmpool->update_history(vm); vm->cp_history(); @@ -993,7 +989,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 246bea7384..33698c546c 100644 --- a/src/lcm/LifeCycleStates.cc +++ b/src/lcm/LifeCycleStates.cc @@ -299,20 +299,14 @@ void LifeCycleManager::deploy_success_action(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); - } - vm->set_state(VirtualMachine::RUNNING); vm->clear_action(); + vm->set_etime(0); + + vm->set_running_etime(0); + vmpool->update_history(vm); vmpool->update(vm); @@ -340,12 +334,12 @@ void LifeCycleManager::deploy_failure_action(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 //---------------------------------------------------- @@ -382,50 +376,44 @@ void LifeCycleManager::deploy_failure_action(int vid) vm->log("LCM", Log::INFO, "Fail to live migrate VM." " Assuming that the VM is still RUNNING."); + + vm->unlock(); + + return; } else if (vm->get_lcm_state() == VirtualMachine::BOOT) { vm->set_state(VirtualMachine::BOOT_FAILURE); - - vmpool->update(vm); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_MIGRATE) { vm->set_state(VirtualMachine::BOOT_MIGRATE_FAILURE); - - vmpool->update(vm); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_UNKNOWN) { vm->set_state(VirtualMachine::UNKNOWN); - - vmpool->update(vm); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_POWEROFF) { vm->set_state(VirtualMachine::POWEROFF); vm->set_state(VirtualMachine::LCM_INIT); - - vmpool->update(vm); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_SUSPENDED) { vm->set_state(VirtualMachine::SUSPENDED); vm->set_state(VirtualMachine::LCM_INIT); - - vmpool->update(vm); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_STOPPED) { vm->set_state(VirtualMachine::BOOT_STOPPED_FAILURE); - vmpool->update(vm); + vm->set_etime(the_time); } else if (vm->get_lcm_state() == VirtualMachine::BOOT_UNDEPLOY) { vm->set_state(VirtualMachine::BOOT_UNDEPLOY_FAILURE); - vmpool->update(vm); + vm->set_etime(the_time); } //wrong state + recover failure from failure state else if ( vm->get_lcm_state() != VirtualMachine::BOOT_FAILURE && @@ -436,6 +424,12 @@ void LifeCycleManager::deploy_failure_action(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); + + vmpool->update(vm); + vm->unlock(); } diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index 2d8f892548..290bb1d9fa 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -661,6 +661,7 @@ void Nebula::start(bool bootstrap_only) float cpu_cost; float mem_cost; float disk_cost; + bool showback_only_running; const VectorAttribute * default_cost; @@ -687,8 +688,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/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index d7364ad909..8dd6e6c06d 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -35,11 +35,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); @@ -582,8 +584,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; @@ -726,8 +728,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); @@ -768,28 +773,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); } } }