X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/1afb6751888eb781f1fa1bc7c98b7c7338308c49..HEAD:/src/kernel/resource/VirtualMachineImpl.cpp?ds=sidebyside diff --git a/src/kernel/resource/VirtualMachineImpl.cpp b/src/kernel/resource/VirtualMachineImpl.cpp index d0162ce547..e8d813ffd8 100644 --- a/src/kernel/resource/VirtualMachineImpl.cpp +++ b/src/kernel/resource/VirtualMachineImpl.cpp @@ -1,31 +1,35 @@ -/* Copyright (c) 2013-2021. The SimGrid Team. All rights reserved. */ +/* Copyright (c) 2013-2023. The SimGrid Team. All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ #include +#include #include #include -#include "simgrid/sg_config.hpp" #include "src/kernel/EngineImpl.hpp" #include "src/kernel/activity/ExecImpl.hpp" #include "src/kernel/resource/VirtualMachineImpl.hpp" -#include "src/surf/cpu_cas01.hpp" -#include "src/surf/cpu_ti.hpp" +#include "src/kernel/resource/models/cpu_cas01.hpp" +#include "src/kernel/resource/models/cpu_ti.hpp" +#include "src/simgrid/module.hpp" +#include "src/simgrid/sg_config.hpp" + +#include XBT_LOG_NEW_DEFAULT_SUBCATEGORY(res_vm, ker_resource, "Virtual Machines, containing actors and mobile across hosts"); -void surf_vm_model_init_HL13(simgrid::kernel::resource::CpuModel* cpu_pm_model) +void simgrid_vm_model_init_HL13() { + auto* cpu_pm_model = simgrid::s4u::Engine::get_instance()->get_netzone_root()->get_impl()->get_cpu_pm_model().get(); auto vm_model = std::make_shared("VM_HL13"); auto* engine = simgrid::kernel::EngineImpl::get_instance(); engine->add_model(vm_model, {cpu_pm_model}); std::shared_ptr cpu_model_vm; - auto cpu_optim = simgrid::config::get_value("cpu/optim"); - if (cpu_optim == "TI") { + if (simgrid::config::get_value("cpu/optim") == "TI") { cpu_model_vm = std::make_shared("VmCpu_TI"); } else { cpu_model_vm = std::make_shared("VmCpu_Cas01"); @@ -37,8 +41,7 @@ void surf_vm_model_init_HL13(simgrid::kernel::resource::CpuModel* cpu_pm_model) namespace simgrid { template class xbt::Extendable; -namespace kernel { -namespace resource { +namespace kernel::resource { /********* * Model * @@ -52,15 +55,15 @@ std::deque VirtualMachineImpl::allVms_; */ const double virt_overhead = 1; // 0.95 -static void host_state_change(s4u::Host const& host) +static void host_onoff(s4u::Host const& host) { if (not host.is_on()) { // just turned off. std::vector trash; /* Find all VMs living on that host */ - for (s4u::VirtualMachine* const& vm : VirtualMachineImpl::allVms_) + for (auto* vm : VirtualMachineImpl::allVms_) if (vm->get_pm() == &host) trash.push_back(vm); - for (s4u::VirtualMachine* vm : trash) + for (auto* vm : trash) vm->shutdown(); } } @@ -70,28 +73,32 @@ static void add_active_exec(s4u::Exec const& task) const s4u::VirtualMachine* vm = dynamic_cast(task.get_host()); if (vm != nullptr) { VirtualMachineImpl* vm_impl = vm->get_vm_impl(); - vm_impl->add_active_exec(); + for (int i = 1; i <= task.get_thread_count(); i++) + vm_impl->add_active_exec(); vm_impl->update_action_weight(); } } -static void remove_active_exec(s4u::Exec const& task) +static void remove_active_exec(s4u::Exec const& exec) { - const s4u::VirtualMachine* vm = dynamic_cast(task.get_host()); + if (not exec.is_assigned()) + return; + const s4u::VirtualMachine* vm = dynamic_cast(exec.get_host()); if (vm != nullptr) { VirtualMachineImpl* vm_impl = vm->get_vm_impl(); - vm_impl->remove_active_exec(); + for (int i = 1; i <= exec.get_thread_count(); i++) + vm_impl->remove_active_exec(); vm_impl->update_action_weight(); } } -static s4u::VirtualMachine* get_vm_from_activity(kernel::activity::ActivityImpl const& act) +static s4u::VirtualMachine* get_vm_from_activity(s4u::Activity const& act) { - auto* exec = dynamic_cast(&act); + const auto* exec = dynamic_cast(act.get_impl()); return exec != nullptr ? dynamic_cast(exec->get_host()) : nullptr; } -static void add_active_activity(kernel::activity::ActivityImpl const& act) +static void add_active_activity(s4u::Activity const& act) { const s4u::VirtualMachine* vm = get_vm_from_activity(act); if (vm != nullptr) { @@ -101,7 +108,7 @@ static void add_active_activity(kernel::activity::ActivityImpl const& act) } } -static void remove_active_activity(kernel::activity::ActivityImpl const& act) +static void remove_active_activity(s4u::Activity const& act) { const s4u::VirtualMachine* vm = get_vm_from_activity(act); if (vm != nullptr) { @@ -113,11 +120,11 @@ static void remove_active_activity(kernel::activity::ActivityImpl const& act) VMModel::VMModel(const std::string& name) : HostModel(name) { - s4u::Host::on_state_change.connect(host_state_change); - s4u::Exec::on_start.connect(add_active_exec); - s4u::Exec::on_completion.connect(remove_active_exec); - activity::ActivityImpl::on_resumed.connect(add_active_activity); - activity::ActivityImpl::on_suspended.connect(remove_active_activity); + s4u::Host::on_onoff_cb(host_onoff); + s4u::Exec::on_start_cb(add_active_exec); + s4u::Exec::on_completion_cb(remove_active_exec); + s4u::Exec::on_resume_cb(add_active_activity); + s4u::Exec::on_suspend_cb(remove_active_activity); } double VMModel::next_occurring_event(double now) @@ -147,7 +154,7 @@ double VMModel::next_occurring_event(double now) **/ /* iterate for all virtual machines */ - for (s4u::VirtualMachine* const& ws_vm : VirtualMachineImpl::allVms_) { + for (auto const* ws_vm : VirtualMachineImpl::allVms_) { if (ws_vm->get_state() == s4u::VirtualMachine::State::SUSPENDED) // Ignore suspended VMs continue; @@ -160,49 +167,109 @@ double VMModel::next_occurring_event(double now) lmm::System* vcpu_system = cpu->get_model()->get_maxmin_system(); vcpu_system->update_constraint_bound(cpu->get_constraint(), virt_overhead * solved_value); } - /* actual next occurring event is determined by VM CPU model at surf_solve */ + /* actual next occurring event is determined by VM CPU model at EngineImpl::solve */ return -1.0; } +Action* VMModel::execute_thread(const s4u::Host* host, double flops_amount, int thread_count) +{ + auto* cpu = host->get_cpu(); + return cpu->execution_start(thread_count * flops_amount, thread_count, -1); +} + /************ * Resource * ************/ VirtualMachineImpl::VirtualMachineImpl(const std::string& name, s4u::VirtualMachine* piface, simgrid::s4u::Host* host_PM, int core_amount, size_t ramsize) - : HostImpl(name, piface), piface_(piface), physical_host_(host_PM), core_amount_(core_amount), ramsize_(ramsize) + : VirtualMachineImpl(name, host_PM, core_amount, ramsize) +{ + set_piface(piface); +} + +VirtualMachineImpl::VirtualMachineImpl(const std::string& name, simgrid::s4u::Host* host_PM, int core_amount, + size_t ramsize) + : HostImpl(name), physical_host_(host_PM), core_amount_(core_amount), ramsize_(ramsize) { - /* Register this VM to the list of all VMs */ - allVms_.push_back(piface); /* We create cpu_action corresponding to a VM process on the host operating system. */ /* TODO: we have to periodically input GUESTOS_NOISE to the system? how ? * The value for GUESTOS_NOISE corresponds to the cost of the global action associated to the VM. It corresponds to * the cost of a VM running no tasks. */ - action_ = physical_host_->get_cpu()->execution_start(0, core_amount_); + action_ = physical_host_->get_cpu()->execution_start(0, core_amount_, 0); // It's empty for now, so it should not request resources in the PM update_action_weight(); - XBT_VERB("Create VM(%s)@PM(%s)", name.c_str(), physical_host_->get_cname()); } +void VirtualMachineImpl::set_piface(s4u::VirtualMachine* piface) +{ + xbt_assert(not piface_, "Pointer to interface already configured for this VM (%s)", get_cname()); + piface_ = piface; + /* Register this VM to the list of all VMs */ + allVms_.push_back(piface); +} + /** @brief A physical host does not disappear in the current SimGrid code, but a VM may disappear during a simulation */ void VirtualMachineImpl::vm_destroy() { - s4u::VirtualMachine::on_destruction(*piface_); /* I was already removed from the allVms set if the VM was destroyed cleanly */ - auto iter = find(allVms_.begin(), allVms_.end(), piface_); - if (iter != allVms_.end()) + if (auto iter = find(allVms_.begin(), allVms_.end(), piface_); iter != allVms_.end()) allVms_.erase(iter); /* Free the cpu_action of the VM. */ XBT_ATTRIB_UNUSED bool ret = action_->unref(); xbt_assert(ret, "Bug: some resource still remains"); + + // VM uses the host's netpoint, clean but don't destroy it + get_iface()->set_netpoint(nullptr); + // Take a temporary copy to delete iface safely after impl is destroy'ed + const auto* iface = get_iface(); + // calls the HostImpl() destroy, it'll delete the impl object + destroy(); + + delete iface; } -void VirtualMachineImpl::suspend(smx_actor_t issuer) +void VirtualMachineImpl::start() { + s4u::VirtualMachine::on_start(*get_iface()); + get_iface()->on_this_start(*get_iface()); + s4u::VmHostExt::ensureVmExtInstalled(); + + if (physical_host_->extension() == nullptr) + physical_host_->extension_set(new s4u::VmHostExt()); + + if (size_t pm_ramsize = physical_host_->extension()->ramsize; + pm_ramsize && + not physical_host_->extension()->overcommit) { /* Need to verify that we don't overcommit */ + /* Retrieve the memory occupied by the VMs on that host. Yep, we have to traverse all VMs of all hosts for that */ + size_t total_ramsize_of_vms = 0; + for (auto const* ws_vm : allVms_) + if (physical_host_ == ws_vm->get_pm()) + total_ramsize_of_vms += ws_vm->get_ramsize(); + + if (total_ramsize_of_vms + get_ramsize() > pm_ramsize) { + XBT_WARN("cannot start %s@%s due to memory shortage: get_ramsize() %zu, free %zu, pm_ramsize %zu (bytes).", + get_cname(), physical_host_->get_cname(), get_ramsize(), pm_ramsize - total_ramsize_of_vms, pm_ramsize); + throw VmFailureException(XBT_THROW_POINT, + xbt::string_printf("Memory shortage on host '%s', VM '%s' cannot be started", + physical_host_->get_cname(), get_cname())); + } + } + vm_state_ = s4u::VirtualMachine::State::RUNNING; + + s4u::VirtualMachine::on_started(*get_iface()); + get_iface()->on_this_started(*get_iface()); +} + +void VirtualMachineImpl::suspend(const actor::ActorImpl* issuer) +{ + s4u::VirtualMachine::on_suspend(*get_iface()); + get_iface()->on_this_suspend(*get_iface()); + if (vm_state_ != s4u::VirtualMachine::State::RUNNING) throw VmFailureException(XBT_THROW_POINT, xbt::string_printf("Cannot suspend VM %s: it is not running.", piface_->get_cname())); @@ -240,6 +307,8 @@ void VirtualMachineImpl::resume() }); vm_state_ = s4u::VirtualMachine::State::RUNNING; + s4u::VirtualMachine::on_resume(*get_iface()); + get_iface()->on_this_resume(*get_iface()); } /** @brief Power off a VM. @@ -249,7 +318,7 @@ void VirtualMachineImpl::resume() * * @param issuer the actor requesting the shutdown */ -void VirtualMachineImpl::shutdown(smx_actor_t issuer) +void VirtualMachineImpl::shutdown(actor::ActorImpl* issuer) { if (vm_state_ != s4u::VirtualMachine::State::RUNNING) XBT_VERB("Shutting down the VM %s even if it's not running but in state %s", piface_->get_cname(), @@ -265,7 +334,8 @@ void VirtualMachineImpl::shutdown(smx_actor_t issuer) set_state(s4u::VirtualMachine::State::DESTROYED); - /* FIXME: we may have to do something at the surf layer, e.g., vcpu action */ + s4u::VirtualMachine::on_shutdown(*get_iface()); + get_iface()->on_this_shutdown(*get_iface()); } /** @brief Change the physical host on which the given VM is running @@ -280,6 +350,7 @@ void VirtualMachineImpl::set_physical_host(s4u::Host* destination) /* update net_elm with that of the destination physical host */ piface_->set_netpoint(destination->get_netpoint()); + physical_host_->get_impl()->move_vm(this, destination->get_impl()); /* Adapt the speed, pstate and other physical characteristics to the one of our new physical CPU */ piface_->get_cpu()->reset_vcpu(destination->get_cpu()); @@ -294,8 +365,7 @@ void VirtualMachineImpl::set_physical_host(s4u::Host* destination) XBT_CRITICAL("FIXME: need copy the state(?), %f", action_->get_remains_no_update()); /* keep the bound value of the cpu action of the VM. */ - double old_bound = action_->get_bound(); - if (old_bound > 0) { + if (double old_bound = action_->get_bound(); old_bound > 0) { XBT_DEBUG("migrate VM(%s): set bound (%f) at %s", vm_name.c_str(), old_bound, pm_name_dst.c_str()); new_cpu_action->set_bound(old_bound); } @@ -330,6 +400,25 @@ void VirtualMachineImpl::update_action_weight() action_->set_bound(std::min(impact * physical_host_->get_speed(), user_bound_)); } -} // namespace resource -} // namespace kernel +void VirtualMachineImpl::start_migration() +{ + is_migrating_ = true; + s4u::VirtualMachine::on_migration_start(*get_iface()); + get_iface()->on_this_migration_start(*get_iface()); +} + +void VirtualMachineImpl::end_migration() +{ + is_migrating_ = false; + s4u::VirtualMachine::on_migration_end(*get_iface()); + get_iface()->on_this_migration_end(*get_iface()); +} + +void VirtualMachineImpl::seal() +{ + HostImpl::seal(); + s4u::VirtualMachine::on_vm_creation(*get_iface()); +} + +} // namespace kernel::resource } // namespace simgrid