From a47ce47003f276edbe70d6b0536f0f32c96ae212 Mon Sep 17 00:00:00 2001 From: Bruno Donassolo Date: Fri, 8 Apr 2022 10:15:36 +0200 Subject: [PATCH] Hosts and VMs internal refactor. Main changes: - Netzones contains their hosts. - Hosts saves their VMs. - Remove "global" Engine::hosts_. Possible mapped impacts: - Hosts destruction order: it was global in the past, now it depends on the netzones. However, no test affected Other changes: - Move code from VirtualMachine interface to VirtualMachineImpl - Add a HostImpl::create_vm to create VMs: similar to create_host for NetZoneImpl --- .../simgrid/kernel/routing/NetZoneImpl.hpp | 28 ++++++- include/simgrid/s4u/VirtualMachine.hpp | 6 +- src/kernel/EngineImpl.cpp | 6 -- src/kernel/EngineImpl.hpp | 1 - src/kernel/resource/VirtualMachineImpl.cpp | 64 ++++++++++++++- src/kernel/resource/VirtualMachineImpl.hpp | 10 ++- src/kernel/routing/NetZoneImpl.cpp | 67 ++++++++++++++-- src/s4u/s4u_Engine.cpp | 41 +++++----- src/s4u/s4u_Host.cpp | 11 +-- src/s4u/s4u_VirtualMachine.cpp | 67 +--------------- src/surf/HostImpl.cpp | 78 +++++++++++++++++-- src/surf/HostImpl.hpp | 10 ++- 12 files changed, 261 insertions(+), 128 deletions(-) diff --git a/include/simgrid/kernel/routing/NetZoneImpl.hpp b/include/simgrid/kernel/routing/NetZoneImpl.hpp index 72a09c68e8..65e37e07de 100644 --- a/include/simgrid/kernel/routing/NetZoneImpl.hpp +++ b/include/simgrid/kernel/routing/NetZoneImpl.hpp @@ -79,14 +79,15 @@ class XBT_PUBLIC NetZoneImpl : public xbt::PropertyHolder { std::vector vertices_; // would like to use the one defined in the StandardLinkImpl file, but for some reason // this hpp is exported to the users and so cannot include the other internal hpp. - class LinkDeleter { + class ResourceDeleter { public: - void operator()(resource::StandardLinkImpl* link) const; + template void operator()(Resource* res) const; }; - std::map, std::less<>> links_; + std::map, std::less<>> links_; /* save split-duplex links separately, keep links_ with only LinkImpl* seen by the user * members of a split-duplex are saved in the links_ */ std::map, std::less<>> split_duplex_links_; + std::map> hosts_; NetZoneImpl* parent_ = nullptr; std::vector children_; // sub-netzones @@ -184,7 +185,7 @@ public: /** * @brief Searches by the link by its name inside this netzone. - * Recursively searches in child netzones + * Recursively searches in children netzones * * @param name Link name * @return Link object or nullptr if not found @@ -200,6 +201,25 @@ public: */ resource::SplitDuplexLinkImpl* get_split_duplex_link_by_name_or_null(const std::string& name) const; + /** + * @brief Searches for a host by its name (recursively) + * Including children netzones and VMs on physival hosts + * + * @param name Host (or VM) name + * @return HostImpl pointer + */ + resource::HostImpl* get_host_by_name_or_null(const std::string& name) const; + + /** + * @brief Gets list of hosts on this netzone recursively. + * + * Note: This includes hosts on children netzones and VMs on physical hosts. + * + * @param filter Filter function to select specific nodes + * @return List of hosts + */ + std::vector get_filtered_hosts(const std::function& filter) const; + /** @brief Make a host within that NetZone */ s4u::Host* create_host(const std::string& name, const std::vector& speed_per_pstate); /** @brief Create a disk with the disk model from this NetZone */ diff --git a/include/simgrid/s4u/VirtualMachine.hpp b/include/simgrid/s4u/VirtualMachine.hpp index f902d648cb..c4e7dd3a0a 100644 --- a/include/simgrid/s4u/VirtualMachine.hpp +++ b/include/simgrid/s4u/VirtualMachine.hpp @@ -45,8 +45,12 @@ class XBT_PUBLIC VirtualMachine : public s4u::Host { static xbt::signal on_migration_end; static xbt::signal on_destruction; +#ifndef DOXYGEN + friend kernel::resource::VirtualMachineImpl; // calls signals from Impl +#endif + public: - explicit VirtualMachine(const std::string& name, Host* physical_host, int core_amount, size_t ramsize = 1024); + explicit VirtualMachine(const std::string& name, Host* physical_host, int core_amount, size_t ramsize); #ifndef DOXYGEN // No copy/move diff --git a/src/kernel/EngineImpl.cpp b/src/kernel/EngineImpl.cpp index b147a6607b..3d4b00e20b 100644 --- a/src/kernel/EngineImpl.cpp +++ b/src/kernel/EngineImpl.cpp @@ -165,12 +165,6 @@ namespace kernel { EngineImpl::~EngineImpl() { - /* Since hosts_ is a std::map, the hosts are destroyed in the lexicographic order, which ensures that the output is - * reproducible. - */ - while (not hosts_.empty()) - hosts_.begin()->second->destroy(); - /* Also delete the other data */ delete netzone_root_; for (auto const& kv : netpoints_) diff --git a/src/kernel/EngineImpl.hpp b/src/kernel/EngineImpl.hpp index f02256ca99..8a8f973a11 100644 --- a/src/kernel/EngineImpl.hpp +++ b/src/kernel/EngineImpl.hpp @@ -33,7 +33,6 @@ namespace simgrid { namespace kernel { class EngineImpl { - std::map> hosts_; std::unordered_map netpoints_; std::unordered_map mailboxes_; diff --git a/src/kernel/resource/VirtualMachineImpl.cpp b/src/kernel/resource/VirtualMachineImpl.cpp index 2c36cac837..521b1d7d29 100644 --- a/src/kernel/resource/VirtualMachineImpl.cpp +++ b/src/kernel/resource/VirtualMachineImpl.cpp @@ -4,6 +4,7 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #include +#include #include #include @@ -183,7 +184,7 @@ Action* VMModel::execute_thread(const s4u::Host* host, double flops_amount, int 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) + : HostImpl(name), piface_(piface), physical_host_(host_PM), core_amount_(core_amount), ramsize_(ramsize) { /* Register this VM to the list of all VMs */ allVms_.push_back(piface); @@ -196,7 +197,6 @@ VirtualMachineImpl::VirtualMachineImpl(const std::string& name, s4u::VirtualMach // 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()); } @@ -211,10 +211,49 @@ void VirtualMachineImpl::vm_destroy() /* 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); + // calls the HostImpl() destroy, it'll delete the impl object + destroy(); + + delete piface_; +} + +void VirtualMachineImpl::start() +{ + s4u::VirtualMachine::on_start(*get_iface()); + s4u::VmHostExt::ensureVmExtInstalled(); + + if (physical_host_->extension() == nullptr) + physical_host_->extension_set(new s4u::VmHostExt()); + + size_t pm_ramsize = physical_host_->extension()->ramsize; + if (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()); } void VirtualMachineImpl::suspend(const actor::ActorImpl* issuer) { + s4u::VirtualMachine::on_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())); @@ -252,6 +291,7 @@ void VirtualMachineImpl::resume() }); vm_state_ = s4u::VirtualMachine::State::RUNNING; + s4u::VirtualMachine::on_resume(*get_iface()); } /** @brief Power off a VM. @@ -277,6 +317,7 @@ void VirtualMachineImpl::shutdown(actor::ActorImpl* issuer) set_state(s4u::VirtualMachine::State::DESTROYED); + s4u::VirtualMachine::on_shutdown(*get_iface()); /* FIXME: we may have to do something at the surf layer, e.g., vcpu action */ } @@ -292,6 +333,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()); @@ -342,6 +384,24 @@ void VirtualMachineImpl::update_action_weight() action_->set_bound(std::min(impact * physical_host_->get_speed(), user_bound_)); } +void VirtualMachineImpl::start_migration() +{ + is_migrating_ = true; + s4u::VirtualMachine::on_migration_start(*get_iface()); +} + +void VirtualMachineImpl::end_migration() +{ + is_migrating_ = false; + s4u::VirtualMachine::on_migration_end(*get_iface()); +} + +void VirtualMachineImpl::seal() +{ + HostImpl::seal(); + s4u::VirtualMachine::on_creation(*get_iface()); +} + } // namespace resource } // namespace kernel } // namespace simgrid diff --git a/src/kernel/resource/VirtualMachineImpl.hpp b/src/kernel/resource/VirtualMachineImpl.hpp index 30355aa60d..c5a4bc0da7 100644 --- a/src/kernel/resource/VirtualMachineImpl.hpp +++ b/src/kernel/resource/VirtualMachineImpl.hpp @@ -32,6 +32,7 @@ public: explicit VirtualMachineImpl(const std::string& name, s4u::VirtualMachine* piface, s4u::Host* host, int core_amount, size_t ramsize); + void start(); void suspend(const actor::ActorImpl* issuer); void resume(); void shutdown(kernel::actor::ActorImpl* issuer); @@ -42,8 +43,8 @@ public: /** @brief Get the physical host on which the given VM is running */ s4u::Host* get_physical_host() const { return physical_host_; } - sg_size_t get_ramsize() const { return ramsize_; } - void set_ramsize(sg_size_t ramsize) { ramsize_ = ramsize; } + size_t get_ramsize() const { return ramsize_; } + void set_ramsize(size_t ramsize) { ramsize_ = ramsize; } s4u::VirtualMachine::State get_state() const { return vm_state_; } void set_state(s4u::VirtualMachine::State state) { vm_state_ = state; } @@ -61,9 +62,10 @@ public: void add_active_exec() { active_execs_++; } void remove_active_exec() { active_execs_--; } - void start_migration() { is_migrating_ = true; } - void end_migration() { is_migrating_ = false; } + void start_migration(); + void end_migration(); bool is_migrating() const { return is_migrating_; } + void seal() override; private: s4u::VirtualMachine* piface_; diff --git a/src/kernel/routing/NetZoneImpl.cpp b/src/kernel/routing/NetZoneImpl.cpp index a63f8a47c1..c9bdedd4bf 100644 --- a/src/kernel/routing/NetZoneImpl.cpp +++ b/src/kernel/routing/NetZoneImpl.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "src/include/simgrid/sg_config.hpp" #include "src/kernel/EngineImpl.hpp" @@ -15,6 +16,7 @@ #include "src/kernel/resource/NetworkModel.hpp" #include "src/kernel/resource/SplitDuplexLinkImpl.hpp" #include "src/kernel/resource/StandardLinkImpl.hpp" +#include "src/kernel/resource/VirtualMachineImpl.hpp" #include "src/surf/HostImpl.hpp" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ker_routing, kernel, "Kernel routing-related information"); @@ -71,9 +73,9 @@ xbt::signal const& link_list)> NetZoneImpl::on_route_creation; -void NetZoneImpl::LinkDeleter::operator()(resource::StandardLinkImpl* link) const +template void NetZoneImpl::ResourceDeleter::operator()(Resource* res) const { - link->destroy(); + res->destroy(); } NetZoneImpl::NetZoneImpl(const std::string& name) : piface_(this), name_(name) @@ -112,6 +114,14 @@ NetZoneImpl::~NetZoneImpl() for (auto const& nz : children_) delete nz; + /* Since hosts_ is a std::map, the hosts are destroyed in the lexicographic order, which ensures that the output is + * reproducible. + */ + for (auto& host : hosts_) { + host.second->destroy(); + } + hosts_.clear(); + for (auto const& kv : bypass_routes_) delete kv.second; @@ -178,12 +188,13 @@ s4u::Host* NetZoneImpl::create_host(const std::string& name, const std::vectorset_englobing_zone(this)->get_iface(); - res->set_netpoint((new NetPoint(name, NetPoint::Type::Host))->set_englobing_zone(this)); + auto* host = (new resource::HostImpl(name))->set_englobing_zone(this); + hosts_[name] = host; + host->get_iface()->set_netpoint((new NetPoint(name, NetPoint::Type::Host))->set_englobing_zone(this)); - cpu_model_pm_->create_cpu(res, speed_per_pstate); + cpu_model_pm_->create_cpu(host->get_iface(), speed_per_pstate); - return res; + return host->get_iface(); } resource::StandardLinkImpl* NetZoneImpl::do_create_link(const std::string& name, const std::vector& bandwidths) @@ -310,6 +321,50 @@ resource::SplitDuplexLinkImpl* NetZoneImpl::get_split_duplex_link_by_name_or_nul return nullptr; } +resource::HostImpl* NetZoneImpl::get_host_by_name_or_null(const std::string& name) const +{ + for (auto const& kv : hosts_) { + auto* host = kv.second; + if (host->get_name() == name) + return host; + /* keep old behavior where host and VMs were saved together on EngineImpl::hosts_ + * get hosts returns VMs too */ + auto* vm = host->get_vm_by_name_or_null(name); + if (vm) + return vm; + } + + for (const auto* child : children_) { + auto* host = child->get_host_by_name_or_null(name); + if (host) + return host; + } + + return nullptr; +} + +std::vector NetZoneImpl::get_filtered_hosts(const std::function& filter) const +{ + std::vector filtered_list; + for (auto const& kv : hosts_) { + s4u::Host* h = kv.second->get_iface(); + if (filter(h)) + filtered_list.push_back(h); + /* Engine::get_hosts returns the VMs too */ + for (auto* vm : h->get_impl()->get_vms()) { + if (filter(vm)) + filtered_list.push_back(vm); + } + } + + for (const auto* child : children_) { + auto child_links = child->get_filtered_hosts(filter); + filtered_list.insert(filtered_list.end(), std::make_move_iterator(child_links.begin()), + std::make_move_iterator(child_links.end())); + } + return filtered_list; +} + void NetZoneImpl::add_route(NetPoint* /*src*/, NetPoint* /*dst*/, NetPoint* /*gw_src*/, NetPoint* /*gw_dst*/, const std::vector& /*link_list_*/, bool /*symmetrical*/) { diff --git a/src/s4u/s4u_Engine.cpp b/src/s4u/s4u_Engine.cpp index c5a656a64b..858ee1f367 100644 --- a/src/s4u/s4u_Engine.cpp +++ b/src/s4u/s4u_Engine.cpp @@ -19,6 +19,7 @@ #include "src/kernel/resource/SplitDuplexLinkImpl.hpp" #include "src/kernel/resource/StandardLinkImpl.hpp" #include "src/mc/mc_replay.hpp" +#include "src/surf/HostImpl.hpp" #include "xbt/config.hpp" #include @@ -182,55 +183,49 @@ void Engine::load_deployment(const std::string& deploy) const /** Returns the amount of hosts in the platform */ size_t Engine::get_host_count() const { - return pimpl->hosts_.size(); + return get_all_hosts().size(); } std::vector Engine::get_all_hosts() const { - std::vector res; - for (auto const& kv : pimpl->hosts_) - res.push_back(kv.second); - return res; + return get_filtered_hosts([](const Host*) { return true; }); } std::vector Engine::get_filtered_hosts(const std::function& filter) const { std::vector hosts; - for (auto const& kv : pimpl->hosts_) { - if (filter(kv.second)) - hosts.push_back(kv.second); + if (pimpl->netzone_root_) { + hosts = pimpl->netzone_root_->get_filtered_hosts(filter); } + /* Sort hosts in lexicographical order: keep same behavior when the hosts were saved on Engine + * Some tests do a get_all_hosts() and selects hosts in this order */ + std::sort(hosts.begin(), hosts.end(), [](const auto* h1, const auto* h2) { return h1->get_name() < h2->get_name(); }); return hosts; } -void Engine::host_register(const std::string& name, Host* host) -{ - pimpl->hosts_[name] = host; -} - -void Engine::host_unregister(const std::string& name) -{ - pimpl->hosts_.erase(name); -} - /** @brief Find a host from its name. * * @throw std::invalid_argument if the searched host does not exist. */ Host* Engine::host_by_name(const std::string& name) const { - auto host = pimpl->hosts_.find(name); - if (host == pimpl->hosts_.end()) + auto* host = host_by_name_or_null(name); + if (not host) throw std::invalid_argument(std::string("Host not found: '") + name + std::string("'")); - return host->second; + return host; } /** @brief Find a host from its name (or nullptr if that host does not exist) */ Host* Engine::host_by_name_or_null(const std::string& name) const { - auto host = pimpl->hosts_.find(name); - return host == pimpl->hosts_.end() ? nullptr : host->second; + Host* host = nullptr; + if (pimpl->netzone_root_) { + auto* host_impl = pimpl->netzone_root_->get_host_by_name_or_null(name); + if (host_impl) + host = host_impl->get_iface(); + } + return host; } /** @brief Find a link from its name. diff --git a/src/s4u/s4u_Host.cpp b/src/s4u/s4u_Host.cpp index d84f23e6e8..9c0ab22d71 100644 --- a/src/s4u/s4u_Host.cpp +++ b/src/s4u/s4u_Host.cpp @@ -111,11 +111,6 @@ void Host::turn_off() if (is_on()) { const kernel::actor::ActorImpl* self = kernel::actor::ActorImpl::self(); kernel::actor::simcall_answered([this, self] { - for (VirtualMachine* const& vm : kernel::resource::VirtualMachineImpl::allVms_) - if (vm->get_pm() == this) { - vm->shutdown(); - vm->turn_off(); - } this->pimpl_cpu_->turn_off(); this->pimpl_->turn_off(self); @@ -368,12 +363,14 @@ void Host::remove_disk(const std::string& disk_name) VirtualMachine* Host::create_vm(const std::string& name, int core_amount) { - return new VirtualMachine(name, this, core_amount); + return kernel::actor::simcall_answered( + [this, &name, core_amount] { return this->pimpl_->create_vm(name, core_amount); }); } VirtualMachine* Host::create_vm(const std::string& name, int core_amount, size_t ramsize) { - return new VirtualMachine(name, this, core_amount, ramsize); + return kernel::actor::simcall_answered( + [this, &name, core_amount, ramsize] { return this->pimpl_->create_vm(name, core_amount, ramsize); }); } ExecPtr Host::exec_init(double flops) const diff --git a/src/s4u/s4u_VirtualMachine.cpp b/src/s4u/s4u_VirtualMachine.cpp index b53de10f83..b0bb7576aa 100644 --- a/src/s4u/s4u_VirtualMachine.cpp +++ b/src/s4u/s4u_VirtualMachine.cpp @@ -36,66 +36,15 @@ VirtualMachine::VirtualMachine(const std::string& name, s4u::Host* physical_host : Host(new kernel::resource::VirtualMachineImpl(name, this, physical_host, core_amount, ramsize)) , pimpl_vm_(dynamic_cast(Host::get_impl())) { - XBT_DEBUG("Create VM %s", get_cname()); - - /* Currently, a VM uses the network resource of its physical host */ - set_netpoint(physical_host->get_netpoint()); - - // Create a VCPU for this VM - std::vector speeds; - for (unsigned long i = 0; i < physical_host->get_pstate_count(); i++) - speeds.push_back(physical_host->get_pstate_speed(i)); - - physical_host->get_netpoint() - ->get_englobing_zone() - ->get_cpu_vm_model() - ->create_cpu(this, speeds) - ->set_core_count(core_amount) - ->seal(); - - if (physical_host->get_pstate() != 0) - set_pstate(physical_host->get_pstate()); - - seal(); // seal this host - s4u::VirtualMachine::on_creation(*this); } void VirtualMachine::start() { - on_start(*this); - - VmHostExt::ensureVmExtInstalled(); - - kernel::actor::simcall_answered([this]() { - Host* pm = this->pimpl_vm_->get_physical_host(); - if (pm->extension() == nullptr) - pm->extension_set(new VmHostExt()); - - size_t pm_ramsize = pm->extension()->ramsize; - if (pm_ramsize && not pm->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 (VirtualMachine* const& ws_vm : kernel::resource::VirtualMachineImpl::allVms_) - if (pm == 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(), pm->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", - pm->get_cname(), get_cname())); - } - } - this->pimpl_vm_->set_state(State::RUNNING); - }); - - on_started(*this); + kernel::actor::simcall_answered([this]() { pimpl_vm_->start(); }); } void VirtualMachine::suspend() { - on_suspend(*this); const kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self(); kernel::actor::simcall_answered([this, issuer]() { pimpl_vm_->suspend(issuer); }); } @@ -103,14 +52,12 @@ void VirtualMachine::suspend() void VirtualMachine::resume() { pimpl_vm_->resume(); - on_resume(*this); } void VirtualMachine::shutdown() { kernel::actor::ActorImpl* issuer = kernel::actor::ActorImpl::self(); kernel::actor::simcall_answered([this, issuer]() { pimpl_vm_->shutdown(issuer); }); - on_shutdown(*this); } void VirtualMachine::destroy() @@ -122,14 +69,8 @@ void VirtualMachine::destroy() XBT_DEBUG("destroy %s", get_cname()); on_destruction(*this); /* Then, destroy the VM object */ - kernel::actor::simcall_answered([this]() { - get_vm_impl()->vm_destroy(); - get_impl()->destroy(); - - /* Don't free these things twice: they are the ones of my physical host */ - set_netpoint(nullptr); - delete this; - }); + kernel::actor::simcall_answered( + [this]() { get_vm_impl()->get_physical_host()->get_impl()->destroy_vm(get_name()); }); }; if (not this_actor::is_maestro() && this_actor::get_host() == this) { @@ -204,13 +145,11 @@ VirtualMachine* VirtualMachine::set_bound(double bound) void VirtualMachine::start_migration() const { pimpl_vm_->start_migration(); - on_migration_start(*this); } void VirtualMachine::end_migration() const { pimpl_vm_->end_migration(); - on_migration_end(*this); } } // namespace s4u diff --git a/src/surf/HostImpl.cpp b/src/surf/HostImpl.cpp index 0b28ab2a5a..3e763b59d0 100644 --- a/src/surf/HostImpl.cpp +++ b/src/surf/HostImpl.cpp @@ -28,16 +28,9 @@ namespace resource { /************ * Resource * ************/ -HostImpl::HostImpl(const std::string& name, s4u::Host* piface) : piface_(this), name_(name) -{ - xbt_assert(s4u::Host::by_name_or_null(name_) == nullptr, "Refusing to create a second host named '%s'.", get_cname()); - s4u::Engine::get_instance()->host_register(name_, piface); -} - HostImpl::HostImpl(const std::string& name) : piface_(this), name_(name) { xbt_assert(s4u::Host::by_name_or_null(name_) == nullptr, "Refusing to create a second host named '%s'.", get_cname()); - s4u::Engine::get_instance()->host_register(name_, &piface_); } HostImpl::~HostImpl() @@ -57,6 +50,9 @@ HostImpl::~HostImpl() for (auto const& d : disks_) d.second->destroy(); + + for (auto const& vm : vms_) + vm.second->vm_destroy(); } /** @brief Fire the required callbacks and destroy the object @@ -66,7 +62,6 @@ HostImpl::~HostImpl() void HostImpl::destroy() { s4u::Host::on_destruction(*this->get_iface()); - s4u::Engine::get_instance()->host_unregister(std::string(name_)); delete this; } @@ -85,6 +80,12 @@ void HostImpl::turn_on() const /** Kill all actors hosted here */ void HostImpl::turn_off(const actor::ActorImpl* issuer) { + /* turn_off VMs running on host */ + for (const auto& kv : vms_) { + auto* actor = kernel::actor::ActorImpl::self(); + kv.second->shutdown(actor); + kv.second->turn_off(actor); + } for (auto& actor : actor_list_) { XBT_DEBUG("Killing Actor %s@%s on behalf of %s which turned off that host.", actor.get_cname(), actor.get_host()->get_cname(), issuer->get_cname()); @@ -137,6 +138,63 @@ std::vector HostImpl::get_disks() const return disks; } +s4u::VirtualMachine* HostImpl::create_vm(const std::string& name, int core_amount, size_t ramsize) +{ + auto* vm = new s4u::VirtualMachine(name, get_iface(), core_amount, ramsize); + vms_[name] = vm->get_vm_impl(); + + // Create a VCPU for this VM + std::vector speeds; + for (unsigned long i = 0; i < get_iface()->get_pstate_count(); i++) + speeds.push_back(get_iface()->get_pstate_speed(i)); + + auto* cpu = englobing_zone_->get_cpu_vm_model()->create_cpu(vm, speeds)->set_core_count(core_amount); + + if (get_iface()->get_pstate() != 0) + cpu->set_pstate(get_iface()->get_pstate()); + + cpu->seal(); + + /* Currently, a VM uses the network resource of its physical host */ + vm->set_netpoint(get_iface()->get_netpoint()); + + vm->seal(); + + return vm; +} + +void HostImpl::move_vm(VirtualMachineImpl* vm, HostImpl* destination) +{ + xbt_assert(vm && destination); + + vms_.erase(vm->get_name()); + destination->vms_[vm->get_name()] = vm; +} + +void HostImpl::destroy_vm(const std::string& name) +{ + auto* vm = vms_[name]; + vms_.erase(name); + vm->vm_destroy(); +} + +VirtualMachineImpl* HostImpl::get_vm_by_name_or_null(const std::string& name) const +{ + auto vm_it = vms_.find(name); + if (vm_it != vms_.end()) + return vm_it->second; + return nullptr; +} + +std::vector HostImpl::get_vms() const +{ + std::vector vms; + for (const auto& kv : vms_) { + vms.push_back(kv.second->get_iface()); + } + return vms; +} + s4u::Disk* HostImpl::create_disk(const std::string& name, double read_bandwidth, double write_bandwidth) { auto disk = piface_.get_netpoint()->get_englobing_zone()->get_disk_model()->create_disk(name, read_bandwidth, @@ -166,6 +224,10 @@ void HostImpl::seal() /* seal its disks */ for (auto const& disk : disks_) disk.second->seal(); + + /* seal its VMs */ + for (auto const& vm : vms_) + vm.second->seal(); } } // namespace resource } // namespace kernel diff --git a/src/surf/HostImpl.hpp b/src/surf/HostImpl.hpp index c5de6ece95..944844b2c2 100644 --- a/src/surf/HostImpl.hpp +++ b/src/surf/HostImpl.hpp @@ -50,13 +50,13 @@ class XBT_PRIVATE HostImpl : public xbt::PropertyHolder { std::vector actors_at_boot_; s4u::Host piface_; std::map> disks_; + std::map> vms_; xbt::string name_{"noname"}; routing::NetZoneImpl* englobing_zone_ = nullptr; bool sealed_ = false; protected: virtual ~HostImpl(); // Use destroy() instead of this destructor. - HostImpl(const std::string& name, s4u::Host* piface); public: friend VirtualMachineImpl; @@ -66,8 +66,14 @@ public: std::vector get_disks() const; s4u::Disk* create_disk(const std::string& name, double read_bandwidth, double write_bandwidth); + s4u::VirtualMachine* create_vm(const std::string& name, int core_amount, size_t ramsize = 1024); + void destroy_vm(const std::string& name); void add_disk(const s4u::Disk* disk); void remove_disk(const std::string& name); + /** @brief Moves VM from this host to destination. Only sets the vm_ accordingly */ + void move_vm(VirtualMachineImpl* vm, HostImpl* destination); + std::vector get_vms() const; + VirtualMachineImpl* get_vm_by_name_or_null(const std::string& name) const; virtual const s4u::Host* get_iface() const { return &piface_; } virtual s4u::Host* get_iface() { return &piface_; } @@ -89,7 +95,7 @@ public: void remove_actor(actor::ActorImpl* actor) { xbt::intrusive_erase(actor_list_, *actor); } void add_actor_at_boot(actor::ProcessArg* arg) { actors_at_boot_.emplace_back(arg); } - void seal(); + virtual void seal(); template void foreach_actor(F function) { -- 2.20.1