Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into hypervisor
authoralebre <adrien.lebre@inria.fr>
Thu, 31 Jan 2013 22:51:36 +0000 (23:51 +0100)
committeralebre <adrien.lebre@inria.fr>
Thu, 31 Jan 2013 22:51:36 +0000 (23:51 +0100)
20 files changed:
buildtools/Cmake/DefinePackages.cmake
include/msg/datatypes.h
include/msg/msg.h
include/simgrid/simix.h
include/xbt/ex.h
include/xbt/lib.h
src/include/surf/surf.h
src/msg/instr_msg_vm.c
src/msg/msg_global.c
src/msg/msg_host.c
src/msg/msg_private.h
src/msg/msg_process.c
src/msg/msg_vm.c
src/simgrid/sg_config.c
src/simix/smx_smurf_private.h
src/simix/smx_user.c
src/simix/smx_vm.c [new file with mode: 0644]
src/surf/vm_workstation.c [new file with mode: 0644]
src/xbt/ex.c
src/xbt/lib.c

index d5e3939..9b0323b 100644 (file)
@@ -216,6 +216,7 @@ set(SURF_SRC
   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
   )
 
@@ -233,6 +234,7 @@ set(SIMIX_SRC
   src/simix/smx_smurf.c
   src/simix/smx_synchro.c
   src/simix/smx_user.c
+  src/simix/smx_vm.c
   )
 
 set(SIMGRID_SRC
index 0536dbb..e5b3ea1 100644 (file)
@@ -46,7 +46,10 @@ typedef xbt_dictelm_t msg_host_t;
 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
@@ -81,22 +84,42 @@ typedef struct msg_task {
  */
 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;
index 330ed56..daa3818 100644 (file)
@@ -341,7 +341,12 @@ XBT_PUBLIC(int) MSG_get_channel_number(void);
  *
  */
 /* 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);
index a856c0b..7e678c6 100644 (file)
@@ -328,6 +328,13 @@ XBT_PUBLIC(e_smx_state_t) simcall_host_execution_get_state(smx_action_t executio
 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 */
index 82573e0..b101562 100644 (file)
@@ -262,7 +262,8 @@ typedef enum {
   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);
index cdc9fc7..3b0ef3c 100644 (file)
@@ -26,10 +26,12 @@ XBT_PUBLIC(void) xbt_lib_free(xbt_lib_t * lib);
 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)
 
index 5a612ac..441070f 100644 (file)
@@ -276,8 +276,14 @@ typedef struct surf_workstation_model_extension_public {
 
 } 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
@@ -323,6 +329,8 @@ typedef struct surf_model {
     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;
@@ -600,6 +608,16 @@ XBT_PUBLIC_DATA(s_surf_model_description_t) surf_storage_model_description[];
  */
 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
  *
index 7b7e3e4..770f4cf 100644 (file)
@@ -13,7 +13,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY (instr_msg_vm, instr, "MSG VM");
 
 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)
@@ -66,6 +66,20 @@ void TRACE_msg_vm_create (const char *vm_name, msg_host_t host)
   }
 }
 
+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;
index 3a3ad8c..de97107 100644 (file)
@@ -37,7 +37,7 @@ void MSG_init_nocheck(int *argc, char **argv) {
 
   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);
     
@@ -49,7 +49,7 @@ void MSG_init_nocheck(int *argc, char **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();
index a767553..8098e23 100644 (file)
@@ -30,9 +30,8 @@ msg_host_t __MSG_host_create(smx_host_t workstation)
 {
   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;
index cbc10c8..cfc2121 100644 (file)
@@ -68,8 +68,6 @@ typedef struct simdata_process {
   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;
 
index 097cfaa..471e2a6 100644 (file)
@@ -50,12 +50,6 @@ void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc)
     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);
 }
index c025372..71a614d 100644 (file)
@@ -3,6 +3,12 @@
 /* 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
  *
@@ -128,86 +229,87 @@ void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination) {
  * 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) {
@@ -216,11 +318,7 @@ void MSG_vm_destroy(msg_vm_t vm) {
     simdata->vm = NULL;
   }
 
-  #ifdef HAVE_TRACING
-  TRACE_msg_vm_end(vm);
-  #endif
-
-
   xbt_dynar_free(&vm->processes);
   xbt_free(vm);
+#endif
 }
index 3d853d4..1b8a6a6 100644 (file)
@@ -785,6 +785,9 @@ void surf_config_models_setup()
   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();
index aaa090f..fcd229d 100644 (file)
@@ -274,6 +274,13 @@ ACTION(SIMCALL_HOST_EXECUTION_GET_REMAINS, host_execution_get_remains, WITH_ANSW
 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 \
index b9099f5..6743b04 100644 (file)
@@ -274,6 +274,44 @@ e_smx_state_t simcall_host_execution_wait(smx_action_t execution)
   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.
diff --git a/src/simix/smx_vm.c b/src/simix/smx_vm.c
new file mode 100644 (file)
index 0000000..e00aabc
--- /dev/null
@@ -0,0 +1,163 @@
+/* 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);
+}
diff --git a/src/surf/vm_workstation.c b/src/surf/vm_workstation.c
new file mode 100644 (file)
index 0000000..94933eb
--- /dev/null
@@ -0,0 +1,81 @@
+/* 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);
+}
index ac2fa9b..7faa0f0 100644 (file)
@@ -222,6 +222,9 @@ const char *xbt_ex_catname(xbt_errcat_t cat)
     return "tracing error";
   case io_error:
     return "io error";
+  case vm_error:
+    return "vm error";
+
   }
   return "INVALID ERROR";
 }
index ccb1e0e..a76ca15 100644 (file)
@@ -70,6 +70,37 @@ void xbt_lib_set(xbt_lib_t lib, const char *key, int level, void *obj)
   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);
@@ -85,3 +116,7 @@ void *xbt_lib_get_level(xbt_dictelm_t elm, int level){
   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);
+}