src/surf/trace_mgr.c
src/surf/workstation.c
src/surf/workstation_ptask_L07.c
+ src/surf/vm_workstation.c
src/xbt/xbt_sg_stubs.c
)
src/simix/smx_smurf.c
src/simix/smx_synchro.c
src/simix/smx_user.c
+ src/simix/smx_vm.c
)
set(SIMGRID_SRC
typedef s_xbt_dictelm_t s_msg_host_t;
typedef struct msg_host_priv {
- xbt_swag_t vms;
+
+ // TODO Warning keeping such vms attribut may lead to some complexity at the SURF Level.
+ // Please check with Arnaud
+ xbt_dynar_t vms;
#ifdef MSG_USE_DEPRECATED
msg_mailbox_t *mailboxes; /**< the channels */
#endif
*/
typedef struct msg_task *msg_task_t;
+/* ******************************** Hypervisor ************************************* */
+typedef struct msg_hypervisor *msg_hypervisor_t;
+
+typedef struct msg_hypervisor {
+ const char *name;
+ s_xbt_swag_hookup_t all_hypervisor_hookup;
+ xbt_dynar_t vms; // vms on this hypervisor
+ msg_host_t host; // physical host of this hypervisor
+
+/* The hypervisor object does not have parameters like the number of CPU
+* cores and the size of memory. These parameters come from those of the
+* physical host.
+**/
+ int overcommit;
+
+} s_msg_hypervisor_t;
+
/* ******************************** VM ************************************* */
-typedef struct msg_vm *msg_vm_t;
+typedef msg_host_t msg_vm_t;
+typedef msg_host_priv_t msg_vm_priv_t;
typedef enum {
- msg_vm_state_suspended, msg_vm_state_running, msg_vm_state_migrating
+msg_vm_state_created,
+msg_vm_state_running,
+msg_vm_state_sleeping,
+msg_vm_state_migrating,
+msg_vm_state_resuming,
+msg_vm_state_suspended,
+msg_vm_state_saved,
+msg_vm_state_restoring,
} e_msg_vm_state_t;
-typedef struct msg_vm {
- const char *name;
- s_xbt_swag_hookup_t all_vms_hookup;
- s_xbt_swag_hookup_t host_vms_hookup;
- xbt_dynar_t processes;
- e_msg_vm_state_t state;
- msg_host_t location;
- int coreAmount;
-} s_msg_vm_t;
+static inline msg_vm_priv_t MSG_vm_priv(msg_vm_t vm){
+ return xbt_lib_get_level(vm, MSG_HOST_LEVEL);
+}
+
/* ******************************** File ************************************ */
typedef struct simdata_file *simdata_file_t;
*
*/
/* This function should not be called directly, but rather from MSG_vm_start_from_template that does not exist yet*/
-XBT_PUBLIC(msg_vm_t) MSG_vm_start(msg_host_t location, const char *name, int coreAmount);
+
+// TODO add VDI later
+XBT_PUBLIC(msg_vm_t) MSG_vm_create(msg_host_t location, const char *name,
+ int core_nb, int mem_cap, int net_cap);
+
+XBT_PUBLIC(void) MSG_vm_start(msg_vm_t);
XBT_PUBLIC(int) MSG_vm_is_suspended(msg_vm_t);
XBT_PUBLIC(int) MSG_vm_is_running(msg_vm_t);
XBT_PUBLIC(void) simcall_host_execution_set_priority(smx_action_t execution, double priority);
XBT_PUBLIC(e_smx_state_t) simcall_host_execution_wait(smx_action_t execution);
+/******************************* VM simcalls ********************************/
+// Create the vm_workstation at the SURF level
+XBT_PUBLIC(void*) simcall_vm_ws_create(const char *name, smx_host_t host);
+XBT_PUBLIC(void*) simcall_get_vm_state(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_start(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_suspend(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_destroy(smx_host_t vm);
/**************************** Process simcalls ********************************/
/* Constructor and Destructor */
thread_error, /**< error while [un]locking */
host_error, /**< host failed */
tracing_error, /**< error during the simulation tracing */
- io_error /**< disk or file error */
+ io_error, /**< disk or file error */
+ vm_error /**< vm error */
} xbt_errcat_t;
XBT_PUBLIC(const char *) xbt_ex_catname(xbt_errcat_t cat);
XBT_PUBLIC(int) xbt_lib_add_level(xbt_lib_t lib, void_f_pvoid_t free_f);
XBT_PUBLIC(void) xbt_lib_set(xbt_lib_t lib, const char *name, int level,
void *obj);
+XBT_PUBLIC(void) xbt_lib_unset(xbt_lib_t lib, const char *key, int level);
XBT_PUBLIC(void *) xbt_lib_get_or_null(xbt_lib_t lib, const char *name,
int level);
XBT_PUBLIC(xbt_dictelm_t) xbt_lib_get_elm_or_null(xbt_lib_t lib, const char *key);
XBT_PUBLIC(void *) xbt_lib_get_level(xbt_dictelm_t elm, int level);
+XBT_PUBLIC(void) xbt_lib_remove(xbt_lib_t lib, const char *key);
#define xbt_lib_length(lib) xbt_dict_length((lib)->dict)
} s_surf_model_extension_workstation_t;
-
-
+typedef struct surf_vm_workstation_model_extension_public {
+ s_surf_model_extension_workstation_t basic;
+ void* (*create) (const char *name, void *ind_phys_workstation); // First operation of the VM model
+ // start does not appear here as it corresponds to turn the state from created to running (see smx_vm.c)
+ int (*get_state) (void *ind_phys_workstation);
+ void (*set_state) (void *ind_phys_workstation, int state);
+ void (*destroy) (void *ind_phys_workstation); // will be vm_ws_destroy(), which destroies the vm-specific data
+} s_surf_model_extension_vm_workstation_t;
/** \ingroup SURF_models
* \brief Model datatype
s_surf_model_extension_network_t network;
s_surf_model_extension_storage_t storage;
s_surf_model_extension_workstation_t workstation;
+ // TODO Implement the corresponding model
+ s_surf_model_extension_vm_workstation_t vm_workstation;
/*******************************************/
/* TUTORIAL: New model */
s_surf_model_extension_new_model_t new_model;
*/
XBT_PUBLIC_DATA(surf_model_t) surf_workstation_model;
+/** \ingroup SURF_models
+ * \brief The vm_workstation model
+ *
+ * Note that when you create an API on top of SURF,
+ * the vm_workstation model should be the only one you use
+ * because depending on the platform model, the network model and the CPU model
+ * may not exist.
+ */
+XBT_PUBLIC_DATA(surf_model_t) surf_vm_workstation_model;
+
/** \ingroup SURF_models
* \brief Initializes the platform with a compound workstation model
*
char *instr_vm_id (msg_vm_t vm, char *str, int len)
{
- return instr_vm_id_2 (vm->name, str, len);
+ return instr_vm_id_2 (MSG_get_vm_name(vm), str, len);
}
char *instr_vm_id_2 (const char *vm_name, char *str, int len)
}
}
+void TRACE_msg_vm_start (msg_vm_t vm)
+{
+ if (TRACE_msg_vm_is_enabled()){
+ int len = INSTR_DEFAULT_STR_SIZE;
+ char str[INSTR_DEFAULT_STR_SIZE];
+
+ container_t vm_container = PJ_container_get (instr_vm_id(vm, str, len));
+ type_t type = PJ_type_get ("MSG_VM_STATE", vm_container->type);
+ val_t value = PJ_value_get ("start", type);
+ new_pajePushState (MSG_get_clock(), vm_container, type, value);
+ }
+
+}
+
void TRACE_msg_vm_kill(msg_vm_t vm) {
if (TRACE_msg_vm_is_enabled()) {
int len = INSTR_DEFAULT_STR_SIZE;
xbt_getpid = MSG_process_self_PID;
if (!msg_global) {
- s_msg_vm_t vm; // to compute the offset
+ // s_msg_vm_t vm; // to compute the offset
SIMIX_global_init(argc, argv);
msg_global->sent_msg = 0;
msg_global->task_copy_callback = NULL;
msg_global->process_data_cleanup = NULL;
- msg_global->vms = xbt_swag_new(xbt_swag_offset(vm,all_vms_hookup));
+// msg_global->vms = xbt_swag_new(xbt_swag_offset(vm,all_vms_hookup));
/* initialization of the action module */
_MSG_action_init();
{
const char *name = SIMIX_host_get_name(workstation);
msg_host_priv_t host = xbt_new0(s_msg_host_priv_t, 1);
- s_msg_vm_t vm; // simply to compute the offset
- host->vms = xbt_swag_new(xbt_swag_offset(vm,host_vms_hookup));
+ host->vms = xbt_dynar_new(sizeof(msg_vm_t),NULL);
#ifdef MSG_USE_DEPRECATED
int i;
int argc; /* arguments number if any */
msg_error_t last_errno; /* the last value returned by a MSG_function */
- msg_vm_t vm; /* virtual machine the process is in */
-
void* data; /* user data */
} s_simdata_process_t, *simdata_process_t;
msg_global->process_data_cleanup(msg_proc->data);
}
- // remove the process from its virtual machine
- if (msg_proc->vm) {
- int pos = xbt_dynar_search(msg_proc->vm->processes,&smx_proc);
- xbt_dynar_remove_at(msg_proc->vm->processes,pos, NULL);
- }
-
// free the MSG process
xbt_free(msg_proc);
}
/* 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. */
+
+// TODO
+// 1./ check how and where a new VM is added to the list of the hosts
+// 2./ MSG_TRACE can be revisited in order to use the host
+
+
#include "msg_private.h"
#include "xbt/sysdep.h"
#include "xbt/log.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_vm, msg,
"Cloud-oriented parts of the MSG API");
-/** @brief Create a new (empty) VMs.
- * @ingroup msg_VMs
+
+/* **** ******** GENERAL ********* **** */
+
+/** \ingroup m_vm_management
+ * \brief Returns the value of a given vm property
*
- * @bug it is expected that in the future, the coreAmount parameter will be used
- * to add extra constraints on the execution, but the argument is ignored for now.
+ * \param vm a vm
+ * \param name a property name
+ * \return value of a property (or NULL if property not set)
*/
-msg_vm_t MSG_vm_start(msg_host_t location, const char *name, int coreAmount) {
- msg_vm_t res = xbt_new0(s_msg_vm_t,1);
- res->all_vms_hookup.prev = NULL;
- res->host_vms_hookup.prev = NULL;
- res->state = msg_vm_state_running;
- res->location = location;
- res->coreAmount = coreAmount;
- res->name = xbt_strdup(name);
- res->processes = xbt_dynar_new(sizeof(msg_process_t),NULL);
+const char *MSG_vm_get_property_value(msg_vm_t vm, const char *name)
+{
+ return MSG_host_get_property_value(vm, name);
+}
- xbt_swag_insert(res,msg_global->vms);
- xbt_swag_insert(res, MSG_host_priv(location)->vms);
+/** \ingroup m_vm_management
+ * \brief Returns a xbt_dict_t consisting of the list of properties assigned to this host
+ *
+ * \param vm a vm
+ * \return a dict containing the properties
+ */
+xbt_dict_t MSG_vm_get_properties(msg_vm_t vm)
+{
+ xbt_assert((vm != NULL), "Invalid parameters (vm is NULL)");
- #ifdef HAVE_TRACING
- TRACE_msg_vm_create(name, location);
- #endif
+ return (simcall_host_get_properties(vm));
+}
+/** \ingroup m_host_management
+ * \brief Change the value of a given host property
+ *
+ * \param host a host
+ * \param name a property name
+ * \param value what to change the property to
+ * \param free_ctn the freeing function to use to kill the value on need
+ */
+void MSG_vm_set_property_value(msg_vm_t vm, const char *name, void *value,void_f_pvoid_t free_ctn) {
- return res;
+ xbt_dict_set(MSG_host_get_properties(vm), name, value,free_ctn);
}
-/** @brief Returns a newly constructed dynar containing all existing VMs in the system.
- * @ingroup msg_VMs
+
+/** \ingroup msg_vm_management
+ * \brief Finds a msg_vm_t using its name.
*
- * Don't forget to free the dynar after use.
+ * This is a name directory service
+ * \param name the name of a vm.
+ * \return the corresponding vm
+ *
+ * Please note that a VM is a specific host. Hence, you should give a different name
+ * for each VM/PM.
*/
-xbt_dynar_t MSG_vms_as_dynar(void) {
- xbt_dynar_t res = xbt_dynar_new(sizeof(msg_vm_t),NULL);
- msg_vm_t vm;
- xbt_swag_foreach(vm,msg_global->vms) {
- xbt_dynar_push(res,&vm);
- }
- return res;
+
+msg_vm_t MSG_vm_get_by_name(const char *name){
+ return MSG_get_host_by_name(name);
}
-/** @brief Returns whether the given VM is currently suspended
- * @ingroup msg_VMs
+/** \ingroup m_vm_management
+ *
+ * \brief Return the name of the #msg_host_t.
+ *
+ * This functions checks whether \a host is a valid pointer or not and return
+ its name.
*/
-int MSG_vm_is_suspended(msg_vm_t vm) {
- return vm->state == msg_vm_state_suspended;
+const char *MSG_vm_get_name(msg_vm_t vm) {
+ return MSG_host_get_name(vm);
}
-/** @brief Returns whether the given VM is currently running
- * @ingroup msg_VMs
+
+/* **** ******** MSG vm actions ********* **** */
+
+/** @brief Create a new VM (the VM is just attached to the location but it is not started yet).
+ * @ingroup msg_VMs*
+ *
+ * Please note that a VM is a specific host. Hence, you should give a different name
+ * for each VM/PM.
*/
-int MSG_vm_is_running(msg_vm_t vm) {
- return vm->state == msg_vm_state_running;
+msg_vm_t MSG_vm_create(msg_host_t ind_host, const char *name,
+ int core_nb, int mem_cap, int net_cap){
+
+ // Note new and vm_workstation refer to the same area (due to the lib/dict appraoch)
+ msg_vm_t new = NULL;
+ void *ind_vm_workstation = NULL;
+ // Ask simix to create the surf vm resource
+ ind_vm_workstation = simcall_vm_ws_create(name,ind_host);
+ new = (msg_vm_t) __MSG_host_create(ind_vm_workstation);
+
+ MSG_vm_set_property_value(new, "CORE_NB", bprintf("%d", core_nb), free);
+ MSG_vm_set_property_value(new, "MEM_CAP", bprintf("%d", core_nb), free);
+ MSG_vm_set_property_value(new, "NET_CAP", bprintf("%d", core_nb), free);
+
+ XBT_DEBUG("A new VM has been created");
+ // TODO check whether the vm (i.e the virtual host) has been correctly added into the list of all hosts.
+
+ #ifdef HAVE_TRACING
+ TRACE_msg_vm_create(name, ind_host);
+ #endif
+
+ return new;
}
-/** @brief Add the given process into the VM.
+
+/** @brief Start a vm (ie. boot)
* @ingroup msg_VMs
*
- * Afterward, when the VM is migrated or suspended or whatever, the process will have the corresponding handling, too.
+ * If the VM cannot be started, an exception is generated.
*
*/
-void MSG_vm_bind(msg_vm_t vm, msg_process_t process) {
- /* check if the process is already in a VM */
- simdata_process_t simdata = simcall_process_get_data(process);
- if (simdata->vm) {
- msg_vm_t old_vm = simdata->vm;
- int pos = xbt_dynar_search(old_vm->processes,&process);
- xbt_dynar_remove_at(old_vm->processes,pos, NULL);
- }
- /* check if the host is in the right host */
- if (simdata->m_host != vm->location) {
- MSG_process_migrate(process,vm->location);
- }
- simdata->vm = vm;
+void MSG_vm_start(msg_vm_t vm) {
- XBT_DEBUG("binding Process %s to %p",MSG_process_get_name(process),vm);
+ //Please note that vm start can raise an exception if the VM cannot be started.
+ simcall_vm_start(vm);
- xbt_dynar_push_as(vm->processes,msg_process_t,process);
+ #ifdef HAVE_TRACING
+ TRACE_msg_vm_start(vm);
+ #endif
+}
+
+/* **** Check state of a VM **** */
+int __MSG_vm_is_state(msg_vm_t vm, e_msg_vm_state_t state) {
+ return simcall_get_vm_state(vm) == state ;
}
-/** @brief Removes the given process from the given VM, and kill it
+
+/** @brief Returns whether the given VM is currently suspended
* @ingroup msg_VMs
- *
- * Will raise a not_found exception if the process were not binded to that VM
*/
-void MSG_vm_unbind(msg_vm_t vm, msg_process_t process) {
- int pos = xbt_dynar_search(vm->processes,process);
- xbt_dynar_remove_at(vm->processes,pos, NULL);
- MSG_process_kill(process);
+int MSG_vm_is_suspended(msg_vm_t vm) {
+ return __MSG_vm_is_state(vm, msg_vm_state_suspended);
}
-
-/** @brief Immediately change the host on which all processes are running.
+/** @brief Returns whether the given VM is currently running
* @ingroup msg_VMs
- *
- * No migration cost occurs. If you want to simulate this too, you want to use a
- * MSG_task_send() before or after, depending on whether you want to do cold or hot
- * migration.
*/
-void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination) {
- unsigned int cpt;
- msg_process_t process;
- xbt_dynar_foreach(vm->processes,cpt,process) {
- MSG_process_migrate(process,destination);
- }
- xbt_swag_remove(vm, MSG_host_priv(vm->location)->vms);
- xbt_swag_insert_at_tail(vm, MSG_host_priv(destination)->vms);
-
- #ifdef HAVE_TRACING
- TRACE_msg_vm_change_host(vm,vm->location,destination);
- #endif
+int MSG_vm_is_running(msg_vm_t vm) {
+ return __MSG_vm_is_state(vm, msg_vm_state_running);
+}
+
+// TODO Implement the functions for the different state
+
+void MSG_vm_shutdown(msg_vm_t vm)
+{
+ /* msg_vm_t equals to msg_host_t */
+ simcall_vm_shutdown(vm);
- vm->location = destination;
+ // #ifdef HAVE_TRACING
+ // TRACE_msg_vm_(vm);
+ // #endif
}
+
+///** @brief Add the given process into the VM.
+// * @ingroup msg_VMs
+// *
+// * Afterward, when the VM is migrated or suspended or whatever, the process will have the corresponding handling, too.
+// *
+// */
+//void MSG_vm_bind(msg_vm_t vm, msg_process_t process) {
+// /* check if the process is already in a VM */
+// simdata_process_t simdata = simcall_process_get_data(process);
+// if (simdata->vm) {
+// msg_vm_t old_vm = simdata->vm;
+// int pos = xbt_dynar_search(old_vm->processes,&process);
+// xbt_dynar_remove_at(old_vm->processes,pos, NULL);
+// }
+// /* check if the host is in the right host */
+// if (simdata->m_host != vm->location) {
+// MSG_process_migrate(process,vm->location);
+// }
+// simdata->vm = vm;
+//
+// XBT_DEBUG("binding Process %s to %p",MSG_process_get_name(process),vm);
+//
+// xbt_dynar_push_as(vm->processes,msg_process_t,process);
+//}
+///** @brief Removes the given process from the given VM, and kill it
+// * @ingroup msg_VMs
+// *
+// * Will raise a not_found exception if the process were not binded to that VM
+// */
+//void MSG_vm_unbind(msg_vm_t vm, msg_process_t process) {
+// int pos = xbt_dynar_search(vm->processes,process);
+// xbt_dynar_remove_at(vm->processes,pos, NULL);
+// MSG_process_kill(process);
+//}
+//
+///** @brief Immediately change the host on which all processes are running.
+// * @ingroup msg_VMs
+// *
+// * No migration cost occurs. If you want to simulate this too, you want to use a
+// * MSG_task_send() before or after, depending on whether you want to do cold or hot
+// * migration.
+// */
+//void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination) {
+// unsigned int cpt;
+// msg_process_t process;
+// xbt_dynar_foreach(vm->processes,cpt,process) {
+// MSG_process_migrate(process,destination);
+// }
+// xbt_swag_remove(vm, MSG_host_priv(vm->location)->vms);
+// xbt_swag_insert_at_tail(vm, MSG_host_priv(destination)->vms);
+//
+// #ifdef HAVE_TRACING
+// TRACE_msg_vm_change_host(vm,vm->location,destination);
+// #endif
+//
+// vm->location = destination;
+//}
+//
+
/** @brief Immediately suspend the execution of all processes within the given VM.
* @ingroup msg_VMs
*
* use a \ref MSG_file_write() before or after, depending on the exact semantic
* of VM suspend to you.
*/
-void MSG_vm_suspend(msg_vm_t vm) {
- unsigned int cpt;
- msg_process_t process;
- xbt_dynar_foreach(vm->processes,cpt,process) {
- XBT_DEBUG("suspend process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
- MSG_process_suspend(process);
- }
+void MSG_vm_suspend(msg_vm_t vm)
+{
+ simcall_vm_suspend(vm);
#ifdef HAVE_TRACING
TRACE_msg_vm_suspend(vm);
#endif
-}
-
-/** @brief Immediately resumes the execution of all processes within the given VM.
- * @ingroup msg_VMs
- *
- * No resume cost occurs. If you want to simulate this too, you want to
- * use a \ref MSG_file_read() before or after, depending on the exact semantic
- * of VM resume to you.
- */
-void MSG_vm_resume(msg_vm_t vm) {
+#if 0
unsigned int cpt;
msg_process_t process;
xbt_dynar_foreach(vm->processes,cpt,process) {
- XBT_DEBUG("resume process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
- MSG_process_resume(process);
+ XBT_DEBUG("suspend process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
+ MSG_process_suspend(process);
}
-
- #ifdef HAVE_TRACING
- TRACE_msg_vm_resume(vm);
- #endif
+#endif
}
-/** @brief Immediately kills all processes within the given VM. Any memory that they allocated will be leaked.
+//
+//
+///** @brief Immediately resumes the execution of all processes within the given VM.
+// * @ingroup msg_VMs
+// *
+// * No resume cost occurs. If you want to simulate this too, you want to
+// * use a \ref MSG_file_read() before or after, depending on the exact semantic
+// * of VM resume to you.
+// */
+//void MSG_vm_resume(msg_vm_t vm) {
+// unsigned int cpt;
+// msg_process_t process;
+// xbt_dynar_foreach(vm->processes,cpt,process) {
+// XBT_DEBUG("resume process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
+// MSG_process_resume(process);
+// }
+//
+// #ifdef HAVE_TRACING
+// TRACE_msg_vm_resume(vm);
+// #endif
+//}
+//
+//
+///**
+// * \ingroup msg_VMs
+// * \brief Reboot the VM, restarting all the processes in it.
+// */
+//void MSG_vm_reboot(msg_vm_t vm)
+//{
+// xbt_dynar_t new_processes = xbt_dynar_new(sizeof(msg_process_t),NULL);
+//
+// msg_process_t process;
+// unsigned int cpt;
+//
+// xbt_dynar_foreach(vm->processes,cpt,process) {
+// msg_process_t new_process = MSG_process_restart(process);
+// xbt_dynar_push_as(new_processes,msg_process_t,new_process);
+//
+// }
+//
+// xbt_dynar_foreach(new_processes, cpt, process) {
+// MSG_vm_bind(vm,process);
+// }
+//
+// xbt_dynar_free(&new_processes);
+//}
+//
+
+/** @brief Destroy a VM. Destroy the VM object from the simulation.
* @ingroup msg_VMs
- *
- * No extra delay occurs. If you want to simulate this too, you want to
- * use a #MSG_process_sleep() or something. I'm not quite sure.
*/
-void MSG_vm_shutdown(msg_vm_t vm)
+void MSG_vm_destroy(msg_vm_t vm)
{
- msg_process_t process;
- XBT_DEBUG("%lu processes in the VM", xbt_dynar_length(vm->processes));
- while (xbt_dynar_length(vm->processes) > 0) {
- process = xbt_dynar_get_as(vm->processes,0,msg_process_t);
- MSG_process_kill(process);
- }
+ /* First, terminate all processes on the VM */
+ simcall_vm_shutdown(vm);
+
+ /* Then, destroy the VM object */
+ simcall_vm_destroy(vm);
#ifdef HAVE_TRACING
- TRACE_msg_vm_kill(vm);
+ TRACE_msg_vm_end(vm);
#endif
-}
-/**
- * \ingroup msg_VMs
- * \brief Reboot the VM, restarting all the processes in it.
- */
-void MSG_vm_reboot(msg_vm_t vm)
-{
- xbt_dynar_t new_processes = xbt_dynar_new(sizeof(msg_process_t),NULL);
-
- msg_process_t process;
- unsigned int cpt;
-
- xbt_dynar_foreach(vm->processes,cpt,process) {
- msg_process_t new_process = MSG_process_restart(process);
- xbt_dynar_push_as(new_processes,msg_process_t,new_process);
-
- }
-
- xbt_dynar_foreach(new_processes, cpt, process) {
- MSG_vm_bind(vm,process);
- }
-
- xbt_dynar_free(&new_processes);
-}
-/** @brief Destroy a msg_vm_t.
- * @ingroup msg_VMs
- */
-void MSG_vm_destroy(msg_vm_t vm) {
+#if 0
unsigned int cpt;
msg_process_t process;
xbt_dynar_foreach(vm->processes,cpt,process) {
simdata->vm = NULL;
}
- #ifdef HAVE_TRACING
- TRACE_msg_vm_end(vm);
- #endif
-
-
xbt_dynar_free(&vm->processes);
xbt_free(vm);
+#endif
}
XBT_DEBUG("Call workstation_model_init");
surf_workstation_model_description[workstation_id].model_init_preparse();
+ XBT_DEBUG("Call vm_workstation_model_init");
+ surf_vm_workstation_model_init();
+
XBT_DEBUG("Call storage_model_init");
storage_id = find_model_description(surf_storage_model_description, storage_model_name);
surf_storage_model_description[storage_id].model_init_preparse();
ACTION(SIMCALL_HOST_EXECUTION_GET_STATE, host_execution_get_state, WITH_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
ACTION(SIMCALL_HOST_EXECUTION_SET_PRIORITY, host_execution_set_priority, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t), TDOUBLE(priority)) sep \
ACTION(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
+ACTION(SIMCALL_VM_WS_CREATE, vm_ws_create, WITH_ANSWER, TPTR(result), TSTRING(name), TSPEC(phys_host, smx_host_t)) sep \
+ACTION(SIMCALL_VM_START, vm_start, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_phys_host, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SET_STATE, vm_set_state, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TINT(state)) sep \
+ACTION(SIMCALL_VM_GET_STATE, vm_get_state, WITH_ANSWER, TINT(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_DESTROY, vm_destroy, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SUSPEND, vm_suspend, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SHUTDOWN, vm_shutdown, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
ACTION(SIMCALL_PROCESS_CREATE, process_create, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t*), TSTRING(name), TSPEC(code, xbt_main_func_t), TPTR(data), TSTRING(hostname), TDOUBLE(kill_time), TINT(argc), TSPEC(argv, char**), TSPEC(properties, xbt_dict_t), TINT(auto_restart)) sep \
ACTION(SIMCALL_PROCESS_KILL, process_kill, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
ACTION(SIMCALL_PROCESS_KILLALL, process_killall, WITH_ANSWER, TVOID(result), TINT(reset_pid)) sep \
return simcall_BODY_host_execution_wait(execution);
}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Returns a dict of the properties assigned to a host.
+ *
+ * \param host A host
+ * \return The properties of this host
+ */
+void* simcall_vm_ws_create(const char *name, smx_host_t phys_host){
+ return simcall_BODY_vm_ws_create(name, phys_host);
+}
+
+void simcall_vm_start(smx_host_t vm) {
+{
+ simcall_BODY_set_vm_state(vm, msg_vm_state_running);
+}
+
+void simcall_vm_suspend(smx_host_t vm)
+{
+ /* will jump to SIMIX_pre_vm_suspend */
+ simcall_BODY_vm_suspend(vm);
+}
+
+void simcall_vm_shutdown(smx_host_t vm)
+{
+ /* will jump to SIMIX_pre_vm_shutdown */
+ simcall_BODY_vm_shutdown(vm);
+}
+
+void simcall_vm_destroy(smx_host_t vm)
+{
+ /*
+ * simcall_BODY_ is defined in src/simix/smx_smurf_private.h.
+ * This function will jump to SIMIX_pre_vm_destroy.
+ **/
+ simcall_BODY_vm_destroy(vm);
+}
+
/**
* \ingroup simix_process_management
* \brief Creates and runs a new SIMIX process.
--- /dev/null
+/* Copyright (c) 2007-2012. 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 "smx_private.h"
+#include "xbt/sysdep.h"
+#include "xbt/log.h"
+#include "xbt/dict.h"
+#include "mc/mc.h"
+
+//If you need to log some stuffs, just uncomment these two lines and uses XBT_DEBUG for instance
+//XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_vm, simix,
+// "Logging specific to SIMIX (vms)");
+
+/* **** create a VM **** */
+
+/**
+ * \brief Internal function to create a SIMIX host.
+ * \param name name of the host to create
+ * \param data some user data (may be NULL)
+ */
+smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host)
+{
+
+ smx_host_priv_t smx_host = xbt_new0(s_smx_host_priv_t, 1);
+ s_smx_process_t proc;
+
+ // TODO check why we do not have any VM here and why we have the host_proc_hookup ?
+
+ /* Host structure */
+ smx_host->data = NULL;
+ smx_host->process_list =
+ xbt_swag_new(xbt_swag_offset(proc, host_proc_hookup));
+
+ /* Update global variables */
+ xbt_lib_set(host_lib,name,SIMIX_HOST_LEVEL,smx_host);
+
+ /* Create surf associated resource */
+ // TODO change phys_host into the right workstation surf model
+ surf_vm_workstation_model->extension.vm_workstation.create(name, ind_phys_host);
+
+ return xbt_lib_get_elm_or_null(host_lib, name);
+}
+
+
+smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host){
+ return SIMIX_vm_create(name, ind_phys_host);
+}
+
+
+/* **** start a VM **** */
+int __can_be_started(smx_host_t vm){
+ // TODO add checking code related to overcommitment or not.
+ return 1;
+}
+void SIMIX_vm_start(smx_host_t ind_vm){
+
+ //TODO only start the VM if you can
+ if (can_be_started(ind_vm))
+ SIMIX_set_vm_state(ind_vm, msg_vm_state_running);
+ else
+ THROWF(vm_error, 0, "The VM %s cannot be started", SIMIX_host_get_name(ind_vm));
+}
+
+void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm){
+ SIMIX_vm_start(vm);
+}
+
+/* ***** set/get state of a VM ***** */
+void SIMIX_set_vm_state(smx_host_t ind_vm, int state){
+ surf_vm_workstation_model->extension.vm_workstation.set_state(ind_vm, state);
+}
+void SIMIX_prev_set_vm_state(smx_host_t ind_vm, int state){
+ SIMIX_set_vm_state(ind_vm, state);
+}
+
+int SIMIX_get_vm_state(smx_host_t ind_vm){
+ return surf_vm_workstation_model->extension.vm_workstation.get_state(ind_vm);
+}
+int SIMIX_pre_vm_state(smx_host_t ind_vm){
+ return SIMIX_get_vm_state(ind_vm);
+}
+
+/**
+ * \brief Function to suspend a SIMIX VM host. This function powers off the
+ * VM. All the processes on this VM will be killed. But, the state of the VM is
+ * perserved. We can later start it again.
+ *
+ * \param host the vm host to suspend (a smx_host_t)
+ */
+void SIMIX_vm_suspend(smx_host_t host)
+{
+ /* TODO: check state */
+
+ XBT_DEBUG("%lu processes in the VM", xbt_swag_size(SIMIX_host_priv(host)->process_list));
+
+ smx_process_t smx_process, smx_process_safe;
+ xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(host)->process_list) {
+ XBT_DEBUG("suspend %s", SIMIX_host_get_name(host));
+ simcall_process_suspend(smx_process);
+ }
+
+ /* TODO: Using the variable of the MSG layer is not clean. */
+ SIMIX_set_vm_state(host, msg_vm_state_suspended);
+}
+
+void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t vm){
+ SIMIX_vm_suspend(vm);
+}
+
+/**
+ * \brief Function to shutdown a SIMIX VM host. This function powers off the
+ * VM. All the processes on this VM will be killed. But, the state of the VM is
+ * perserved. We can later start it again.
+ *
+ * \param host the vm host to shutdown (a smx_host_t)
+ */
+void SIMIX_vm_shutdown(smx_host_t host)
+{
+ /* TODO: check state */
+
+ XBT_DEBUG("%lu processes in the VM", xbt_swag_size(SIMIX_host_priv(host)->process_list));
+
+ smx_process_t smx_process, smx_process_safe;
+ xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(host)->process_list) {
+ XBT_DEBUG("kill %s", SIMIX_host_get_name(host));
+ simcall_process_kill(smx_process);
+ }
+
+ /* TODO: Using the variable of the MSG layer is not clean. */
+ SIMIX_set_vm_state(host, msg_vm_state_sleeping);
+}
+
+void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t vm){
+ SIMIX_vm_shutdown(vm);
+}
+
+/**
+ * \brief Function to destroy a SIMIX VM host.
+ *
+ * \param host the vm host to destroy (a smx_host_t)
+ */
+void SIMIX_vm_destroy(smx_host_t ind_vm)
+{
+ /* this code basically performs a similar thing like SIMIX_host_destroy() */
+
+ xbt_assert((host != NULL), "Invalid parameters");
+ char *hostname = SIMIX_host_get_name(ind_vm);
+
+ smx_host_priv_t host_priv = SIMIX_host_priv(host);
+
+ /* this will call the registered callback function, i.e., SIMIX_host_destroy(). */
+ xbt_lib_unset(host_lib, hostname, SIMIX_HOST_LEVEL);
+
+ /* jump to vm_ws_destroy(). The surf level resource will be freed. */
+ surf_vm_workstation_model->extension.vm_workstation.destroy(ind_vm);
+}
+
+void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t vm){
+ SIMIX_vm_destroy(vm);
+}
--- /dev/null
+/* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. 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 "xbt/ex.h"
+#include "xbt/dict.h"
+#include "portable.h"
+#include "surf_private.h"
+#include "surf/surf_resource.h"
+#include "simgrid/sg_config.h"
+
+typedef struct workstation_VM2013 {
+ s_surf_resource_t generic_resource; /* Must remain first to add this to a trace */
+ surf_resource_t physical_workstation; // Pointer to the host OS
+ e_msg_vm_state_t current_state; // See include/msg/datatypes.h
+} s_workstation_VM2013_t, *workstation_VM2013_t;
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_vm_workstation, surf,
+ "Logging specific to the SURF VM workstation module");
+
+surf_model_t surf_vm_workstation_model = NULL;
+
+static void vm_ws_create(const char *name, void *ind_phys_workstation)
+{
+ workstation_VM2013_t vm_ws = xbt_new0(s_workstation_VM2013_t, 1);
+// TODO Complete the surf vm workstation model
+ vm_ws->generic_resource.model = surf_vm_workstation_model;
+ vm_ws->generic_resource.name = xbt_strdup(name);
+ // ind means ''indirect'' that this is a reference on the whole dict_elm structure (i.e not on the surf_resource_private infos)
+ vm_ws->physical_workstation = surf_workstation_resource_priv(ind_phys_workstation);
+ vm_ws->current_state=msg_vm_state_created,
+ xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, vm_ws);
+}
+
+
+/*
+ * A physical host does not disapper in the current SimGrid code, but a VM may
+ * disapper during a simulation.
+ */
+static void vm_ws_destroy(void *ind_phys_workstation)
+{
+ /* ind_phys_workstation equals to smx_host_t */
+ workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_phys_workstation);
+ xbt_assert(vm_ws);
+ xbt_assert(vm_ws->generic_resource.model == surf_vm_workstation_model);
+
+ const char *name = vm_ws->generic_resource.name;
+ /* this will call surf_resource_free() */
+ xbt_lib_unset(host_lib, name, SURF_WKS_LEVEL);
+
+ xbt_free(vm_ws->generic_resource.name);
+ xbt_free(vm_ws);
+}
+
+static int vm_ws_get_state(void *ind_vm_ws){
+ return ((workstation_VM2013_t) surf_workstation_resource_priv(ind_vm_ws))->current_state;
+}
+
+static void vm_ws_set_state(void *ind_vm_ws, int state){
+ ((workstation_VM2013_t) surf_workstation_resource_priv(ind_vm_ws))->current_state=state;
+}
+static void surf_vm_workstation_model_init_internal(void)
+{
+ surf_vm_workstation_model = surf_model_init();
+
+ surf_vm_workstation_model->name = "Virtual Workstation";
+
+ surf_vm_workstation_model->extension.vm_workstation.create = vm_ws_create;
+ surf_vm_workstation_model->extension.vm_workstation.set_state = vm_ws_set_state;
+ surf_vm_workstation_model->extension.vm_workstation.get_state = vm_ws_get_state;
+ surf_vm_workstation_model->extension.vm_workstation.destroy = vm_ws_destroy;
+
+}
+
+void surf_vm_workstation_model_init()
+{
+ surf_vm_workstation_model_init_internal();
+ xbt_dynar_push(model_list, &surf_vm_workstation_model);
+}
return "tracing error";
case io_error:
return "io error";
+ case vm_error:
+ return "vm error";
+
}
return "INVALID ERROR";
}
elts[level] = obj;
}
+/* for vm */
+void xbt_lib_unset(xbt_lib_t lib, const char *key, int level)
+{
+ void **elts = xbt_dict_get_or_null(lib->dict, key);
+ if (!elts) {
+ XBT_WARN("no key %s", key);
+ return;
+ }
+
+ void *obj = elts[level];
+
+ if (!obj) {
+ XBT_WARN("no key %s at level %d", key, level);
+ return;
+ } else {
+ XBT_DEBUG("Remove %p of key %s at level %d", obj, key, level);
+ lib->free_f[level](obj);
+ elts[level] = NULL;
+ }
+
+ /* check if there are elements of this key */
+ int i;
+ for (i = 0; i < lib->levels; i++) {
+ if (elts[i] != NULL)
+ return;
+ }
+
+ /* there is no element at any level, so delete the key */
+ xbt_dict_remove(lib->dict, key);
+}
+
void *xbt_lib_get_or_null(xbt_lib_t lib, const char *key, int level)
{
void **elts = xbt_dict_get_or_null(lib->dict, key);
void **elts = elm->content;
return elts ? elts[level] : NULL;
}
+
+void xbt_lib_remove(xbt_lib_t lib, const char *key){
+ xbt_dict_remove(lib->dict, key);
+}