std::vector<kernel::routing::NetPoint*> 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 <typename Resource> void operator()(Resource* res) const;
};
- std::map<std::string, std::unique_ptr<resource::StandardLinkImpl, LinkDeleter>, std::less<>> links_;
+ std::map<std::string, std::unique_ptr<resource::StandardLinkImpl, ResourceDeleter>, 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::string, std::unique_ptr<resource::SplitDuplexLinkImpl>, std::less<>> split_duplex_links_;
+ std::map<std::string, resource::HostImpl*, std::less<>> hosts_;
NetZoneImpl* parent_ = nullptr;
std::vector<NetZoneImpl*> children_; // sub-netzones
/**
* @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
*/
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<s4u::Host*> get_filtered_hosts(const std::function<bool(s4u::Host*)>& filter) const;
+
/** @brief Make a host within that NetZone */
s4u::Host* create_host(const std::string& name, const std::vector<double>& speed_per_pstate);
/** @brief Create a disk with the disk model from this NetZone */
static xbt::signal<void(VirtualMachine const&)> on_migration_end;
static xbt::signal<void(VirtualMachine const&)> 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
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_)
namespace kernel {
class EngineImpl {
- std::map<std::string, s4u::Host*, std::less<>> hosts_;
std::unordered_map<std::string, routing::NetPoint*> netpoints_;
std::unordered_map<std::string, activity::MailboxImpl*> mailboxes_;
* under the terms of the license (GNU LGPL) which comes with this package. */
#include <simgrid/Exception.hpp>
+#include <simgrid/kernel/routing/NetPoint.hpp>
#include <simgrid/kernel/routing/NetZoneImpl.hpp>
#include <simgrid/s4u/Exec.hpp>
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);
// 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());
}
/* 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<s4u::VmHostExt>() == nullptr)
+ physical_host_->extension_set(new s4u::VmHostExt());
+
+ size_t pm_ramsize = physical_host_->extension<s4u::VmHostExt>()->ramsize;
+ if (pm_ramsize &&
+ not physical_host_->extension<s4u::VmHostExt>()->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()));
});
vm_state_ = s4u::VirtualMachine::State::RUNNING;
+ s4u::VirtualMachine::on_resume(*get_iface());
}
/** @brief Power off a VM.
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 */
}
/* 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());
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
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);
/** @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; }
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_;
#include <simgrid/kernel/routing/NetZoneImpl.hpp>
#include <simgrid/s4u/Engine.hpp>
#include <simgrid/s4u/Host.hpp>
+#include <simgrid/s4u/VirtualMachine.hpp>
#include "src/include/simgrid/sg_config.hpp"
#include "src/kernel/EngineImpl.hpp"
#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");
std::vector<kernel::resource::StandardLinkImpl*> const& link_list)>
NetZoneImpl::on_route_creation;
-void NetZoneImpl::LinkDeleter::operator()(resource::StandardLinkImpl* link) const
+template <typename Resource> void NetZoneImpl::ResourceDeleter::operator()(Resource* res) const
{
- link->destroy();
+ res->destroy();
}
NetZoneImpl::NetZoneImpl(const std::string& name) : piface_(this), name_(name)
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;
"Impossible to create host: %s. Invalid CPU model: nullptr. Have you set the parent of this NetZone: %s?",
name.c_str(), get_cname());
xbt_assert(not sealed_, "Impossible to create host: %s. NetZone %s already sealed", name.c_str(), get_cname());
- auto* res = (new resource::HostImpl(name))->set_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<double>& bandwidths)
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<s4u::Host*> NetZoneImpl::get_filtered_hosts(const std::function<bool(s4u::Host*)>& filter) const
+{
+ std::vector<s4u::Host*> 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<s4u::LinkInRoute>& /*link_list_*/, bool /*symmetrical*/)
{
#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 <algorithm>
/** 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<Host*> Engine::get_all_hosts() const
{
- std::vector<Host*> res;
- for (auto const& kv : pimpl->hosts_)
- res.push_back(kv.second);
- return res;
+ return get_filtered_hosts([](const Host*) { return true; });
}
std::vector<Host*> Engine::get_filtered_hosts(const std::function<bool(Host*)>& filter) const
{
std::vector<Host*> 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.
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);
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
: Host(new kernel::resource::VirtualMachineImpl(name, this, physical_host, core_amount, ramsize))
, pimpl_vm_(dynamic_cast<kernel::resource::VirtualMachineImpl*>(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<double> 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<VmHostExt>() == nullptr)
- pm->extension_set(new VmHostExt());
-
- size_t pm_ramsize = pm->extension<VmHostExt>()->ramsize;
- if (pm_ramsize && not pm->extension<VmHostExt>()->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); });
}
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()
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) {
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
/************
* 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()
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
void HostImpl::destroy()
{
s4u::Host::on_destruction(*this->get_iface());
- s4u::Engine::get_instance()->host_unregister(std::string(name_));
delete this;
}
/** 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());
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<double> 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<s4u::VirtualMachine*> HostImpl::get_vms() const
+{
+ std::vector<s4u::VirtualMachine*> 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,
/* 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
std::vector<actor::ProcessArg*> actors_at_boot_;
s4u::Host piface_;
std::map<std::string, DiskImpl*, std::less<>> disks_;
+ std::map<std::string, VirtualMachineImpl*, std::less<>> 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;
std::vector<s4u::Disk*> 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<s4u::VirtualMachine*> 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_; }
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 <class F> void foreach_actor(F function)
{