Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Now VM operations workig!
authorTakahiro Hirofuchi <t.hirofuchi+sg@aist.go.jp>
Tue, 26 Feb 2013 15:41:41 +0000 (16:41 +0100)
committerTakahiro Hirofuchi <t.hirofuchi+sg@aist.go.jp>
Tue, 26 Feb 2013 15:46:19 +0000 (16:46 +0100)
- Fix the resource deallocation on exit, i.e., delete VM-related objects
  from host_lib without calling the callbacks.
- Implement vm_{suspend/resume, save/restore, shutdown}
- Call SIMIX_simcall_answer() at the end of some SIMIX_functions, so
  that avoid the bug that these functions never return to the userland.
- Delete the use of some simcalls at the SIMIX layer.
- Implement  vm_migrate. It updates the net_elm and PM of the VM.
- Add vm_ws_execute() to add action cost to the vcpu's dummy execution
  action.
- Delete the code around GUESTOS_NOISE. we need to add something like a
  task periodically.

include/simgrid/simix.h
src/include/surf/surf.h
src/msg/msg_vm.c
src/simix/smx_host_private.h
src/simix/smx_smurf_private.h
src/simix/smx_user.c
src/simix/smx_vm.c
src/surf/vm_workstation.c
src/surf/workstation.c
src/surf/workstation_private.h

index e52254c..b7ab1d1 100644 (file)
@@ -326,7 +326,7 @@ XBT_PUBLIC(void*) simcall_vm_create(const char *name, smx_host_t host);
 XBT_PUBLIC(int) simcall_vm_get_state(smx_host_t vm);
 XBT_PUBLIC(void) simcall_vm_start(smx_host_t vm);
 XBT_PUBLIC(void) simcall_vm_migrate(smx_host_t vm, smx_host_t dst_pm);
-XBT_PUBLIC(const char*) simcall_vm_get_phys_host(smx_host_t vm);
+XBT_PUBLIC(void *) simcall_vm_get_pm(smx_host_t vm);
 XBT_PUBLIC(void) simcall_vm_resume(smx_host_t vm);
 XBT_PUBLIC(void) simcall_vm_save(smx_host_t vm);
 XBT_PUBLIC(void) simcall_vm_restore(smx_host_t vm);
index b13bff2..6e1d8f8 100644 (file)
@@ -300,13 +300,23 @@ 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_vm_workstation);
-  void (*set_state) (void *ind_vms_workstation, int state);
-  void (*migrate) (void *ind_vm_workstation, void *ind_dest_phys_workstation); // will be vm_ws_migrate()
-  const char * (*get_phys_host) (void *ind_vm_workstation); // will be vm_ws_get_phys_host()
-  void (*destroy) (void *ind_vm_workstation); // will be vm_ws_destroy(), which destroies the vm-workstation-specific data
+
+  void   (*create)  (const char *name, void *ind_phys_workstation); // First operation of the VM model
+  void   (*destroy) (void *ind_vm_ws); // will be vm_ws_destroy(), which destroies the vm-workstation-specific data
+
+  void   (*suspend) (void *ind_vm_ws);
+  void   (*resume)  (void *ind_vm_ws);
+
+  void   (*save)    (void *ind_vm_ws);
+  void   (*restore) (void *ind_vm_ws);
+
+  void   (*migrate) (void *ind_vm_ws, void *ind_vm_ws_dest); // will be vm_ws_migrate()
+  void * (*get_pm)  (void *ind_vm_ws); // will be vm_ws_get_pmt()
+
+  int    (*get_state) (void *ind_vm_ws);
+  void   (*set_state) (void *ind_vm_ws, int state);
+
 } s_surf_model_extension_vm_workstation_t;
 
 /** \ingroup SURF_models
index 908d89c..45c9bf8 100644 (file)
@@ -256,7 +256,7 @@ void MSG_vm_shutdown(msg_vm_t vm)
  * 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)
+void MSG_vm_migrate(msg_vm_t vm, msg_host_t new_pm)
 {
   /* some thoughts:
    * - One approach is ...
@@ -279,16 +279,14 @@ void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination)
    *   
    */
 
-  #ifdef HAVE_TRACING
-  const char *old_pm_name = simcall_vm_get_phys_host(vm);
-  msg_host_t old_pm_ind  = xbt_lib_get_elm_or_null(host_lib, old_pm_name);
-  #endif
+  msg_host_t old_pm = simcall_vm_get_pm(vm);
 
-  simcall_vm_migrate(vm, destination);
+  simcall_vm_migrate(vm, new_pm);
 
+  XBT_DEBUG("VM(%s) moved from PM(%s) to PM(%s)", vm->key, old_pm->key, new_pm->key);
 
   #ifdef HAVE_TRACING
-  TRACE_msg_vm_change_host(vm, old_pm_ind, destination);
+  TRACE_msg_vm_change_host(vm, old_pm, new_pm);
   #endif
 }
 
@@ -305,6 +303,8 @@ void MSG_vm_suspend(msg_vm_t vm)
 {
   simcall_vm_suspend(vm);
 
+  XBT_DEBUG("vm_suspend done");
+
   #ifdef HAVE_TRACING
   TRACE_msg_vm_suspend(vm);
   #endif
index 17b8241..e3f0870 100644 (file)
@@ -91,39 +91,38 @@ void SIMIX_set_category(smx_action_t action, const char *category);
 smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host);
 smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host);
 
-void SIMIX_vm_start(smx_host_t ind_vm);
-void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm);
-void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm);
-
-const char *SIMIX_vm_get_phys_host(smx_host_t ind_vm);
-const char *SIMIX_pre_vm_get_phys_host(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_set_state(smx_host_t ind_vm, int state);
-void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state);
-
-int SIMIX_vm_get_state(smx_host_t ind_vm);
-int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_resume(smx_host_t ind_vm);
+void SIMIX_vm_destroy(smx_host_t ind_vm);
+void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer);
 void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm);
 
-void SIMIX_vm_suspend(smx_host_t ind_vm);
+void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer);
 void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm);
-
-void SIMIX_vm_save(smx_host_t ind_vm);
+// --
+void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer);
 void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm);
 
-void SIMIX_vm_restore(smx_host_t ind_vm);
+void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer);
 void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_start(smx_host_t ind_vm);
+void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm);
 
 void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer);
 void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_set_state(smx_host_t ind_vm, int state);
+void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state);
 
-void SIMIX_vm_destroy(smx_host_t ind_vm);
-void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm);
+int SIMIX_vm_get_state(smx_host_t ind_vm);
+int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm);
+void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm);
 
+void *SIMIX_vm_get_pm(smx_host_t ind_vm);
+void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm);
 
 #endif
 
index 66df814..4137708 100644 (file)
@@ -275,18 +275,18 @@ 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_CREATE, vm_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_CREATE,    vm_create,    WITH_ANSWER,    TPTR(result),  TSTRING(name), TSPEC(ind_pm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_START,     vm_start,     WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, 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_MIGRATE, vm_migrate, WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(ind_dst_pm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_GET_PHYS_HOST, vm_get_phys_host, WITH_ANSWER, TSTRING(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_RESUME, vm_resume, 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_VM_SAVE, vm_save, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
-ACTION(SIMCALL_VM_RESTORE, vm_restore, WITHOUT_ANSWER, TVOID(result), TSPEC(vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_GET_STATE, vm_get_state, WITH_ANSWER,    TINT(result),  TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_MIGRATE,   vm_migrate,   WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t), TSPEC(ind_dst_pm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_GET_PM,    vm_get_pm,    WITH_ANSWER,    TPTR(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(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_RESUME,    vm_resume,    WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SHUTDOWN,  vm_shutdown,  WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SAVE,      vm_save,      WITHOUT_ANSWER, TVOID(result), TSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_RESTORE,   vm_restore,   WITHOUT_ANSWER, TVOID(result), TSPEC(ind_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 6e745b1..fecc673 100644 (file)
@@ -321,10 +321,10 @@ int simcall_vm_get_state(smx_host_t vm)
  * \param vm VM
  * \return The name of the physical host
  */
-const char *simcall_vm_get_phys_host(smx_host_t vm)
+void *simcall_vm_get_pm(smx_host_t vm)
 {
   /* will jump to SIMIX_pre_vm_migrate in src/simix/smx_smurf_private.h */
-  return simcall_BODY_vm_get_phys_host(vm);
+  return simcall_BODY_vm_get_pm(vm);
 }
 
 /**
index 59156f1..d68acb2 100644 (file)
@@ -44,7 +44,8 @@ smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host)
 }
 
 
-smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host){
+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);
 }
 
@@ -64,10 +65,12 @@ static int __can_be_started(smx_host_t vm)
 {
        // TODO add checking code related to overcommitment or not.
 
+#if 0
   int overcommit = get_host_property_as_integer(vm, "OverCommit");
   int core_nb = get_host_property_as_integer(vm, "CORE_NB");
   int mem_cap = get_host_property_as_integer(vm, "MEM_CAP");
   int net_cap = get_host_property_as_integer(vm, "NET_CAP");
+#endif
 
   /* we need to get other VM objects on this physical host. */
 
@@ -119,19 +122,18 @@ int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm)
  */
 void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm)
 {
-  /* TODO: check state */
+  const char *name = SIMIX_host_get_name(ind_vm);
 
-  /* TODO: Using the variable of the MSG layer is not clean. */
-  SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_MIGRATING);
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", name);
 
   /* jump to vm_ws_migrate(). this will update the vm location. */
   surf_vm_workstation_model->extension.vm_workstation.migrate(ind_vm, ind_dst_pm);
-
-  SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
 }
 
-void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm){
-   SIMIX_vm_migrate(ind_vm, ind_dst_pm);
+void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm)
+{
+  SIMIX_vm_migrate(ind_vm, ind_dst_pm);
 }
 
 
@@ -140,14 +142,15 @@ void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t i
  *
  * \param host the vm host to get_phys_host (a smx_host_t)
  */
-const char *SIMIX_vm_get_phys_host(smx_host_t ind_vm)
+void *SIMIX_vm_get_pm(smx_host_t ind_vm)
 {
-  /* jump to vm_ws_get_phys_host(). this will return the vm name. */
-  return surf_vm_workstation_model->extension.vm_workstation.get_phys_host(ind_vm);
+  /* jump to vm_ws_get_pm(). this will return the vm name. */
+  return surf_vm_workstation_model->extension.vm_workstation.get_pm(ind_vm);
 }
 
-const char *SIMIX_pre_vm_get_phys_host(smx_simcall_t simcall, smx_host_t ind_vm){
-  return SIMIX_vm_get_phys_host(ind_vm);
+void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  return SIMIX_vm_get_pm(ind_vm);
 }
 
 
@@ -158,25 +161,40 @@ const char *SIMIX_pre_vm_get_phys_host(smx_simcall_t simcall, smx_host_t ind_vm)
  *
  * \param host the vm host to suspend (a smx_host_t)
  */
-void SIMIX_vm_suspend(smx_host_t ind_vm)
+void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer)
 {
-  /* TODO: check state */
+  const char *name = SIMIX_host_get_name(ind_vm);
 
-  XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", name);
+
+  XBT_DEBUG("suspend VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  /* jump to vm_ws_suspend. The state will be set. */
+  surf_vm_workstation_model->extension.vm_workstation.suspend(ind_vm);
 
   smx_process_t smx_process, smx_process_safe;
   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
-         XBT_DEBUG("suspend %s", SIMIX_host_get_name(ind_vm));
-        /* FIXME: calling a simcall from the SIMIX layer is strange. */
-         simcall_process_suspend(smx_process);
+    XBT_DEBUG("suspend %s", smx_process->name);
+    SIMIX_process_suspend(smx_process, issuer);
   }
 
-  /* TODO: Using the variable of the MSG layer is not clean. */
-  SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_SUSPENDED);
+  XBT_DEBUG("suspend all processes on the VM done done");
 }
 
-void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm){
-   SIMIX_vm_suspend(ind_vm);
+void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  if (simcall->issuer->smx_host == ind_vm) {
+    XBT_ERROR("cannot suspend the VM where I run");
+    DIE_IMPOSSIBLE;
+  }
+
+  SIMIX_vm_suspend(ind_vm, simcall->issuer);
+
+  /* without this, simcall_vm_suspend() does not return to the userland. why? */
+  SIMIX_simcall_answer(simcall);
+
+  XBT_DEBUG("SIMIX_pre_vm_suspend done");
 }
 
 
@@ -186,25 +204,29 @@ void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm){
  *
  * \param host the vm host to resume (a smx_host_t)
  */
-void SIMIX_vm_resume(smx_host_t ind_vm)
+void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer)
 {
-  /* TODO: check state */
+  const char *name = SIMIX_host_get_name(ind_vm);
 
-  XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SUSPENDED)
+    THROWF(vm_error, 0, "VM(%s) was not suspended", name);
+
+  XBT_DEBUG("resume VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  /* jump to vm_ws_resume() */
+  surf_vm_workstation_model->extension.vm_workstation.resume(ind_vm);
 
   smx_process_t smx_process, smx_process_safe;
   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
-         XBT_DEBUG("resume %s", SIMIX_host_get_name(ind_vm));
-        /* FIXME: calling a simcall from the SIMIX layer is strange. */
-         simcall_process_resume(smx_process);
+    XBT_DEBUG("resume %s", smx_process->name);
+    SIMIX_process_resume(smx_process, issuer);
   }
-
-  /* TODO: Using the variable of the MSG layer is not clean. */
-  SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
 }
 
-void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm){
-   SIMIX_vm_resume(ind_vm);
+void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_resume(ind_vm, simcall->issuer);
+  SIMIX_simcall_answer(simcall);
 }
 
 
@@ -215,27 +237,32 @@ void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm){
  *
  * \param host the vm host to save (a smx_host_t)
  */
-void SIMIX_vm_save(smx_host_t ind_vm)
+void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer)
 {
-  /* TODO: check state */
+  const char *name = SIMIX_host_get_name(ind_vm);
+
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", name);
 
-  XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
 
-  /* TODO: do something at the surf level */
+  XBT_DEBUG("save VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  /* jump to vm_ws_save() */
+  surf_vm_workstation_model->extension.vm_workstation.save(ind_vm);
 
   smx_process_t smx_process, smx_process_safe;
   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
-         XBT_DEBUG("save %s", SIMIX_host_get_name(ind_vm));
-        /* FIXME: calling a simcall from the SIMIX layer is strange. */
-         simcall_process_suspend(smx_process);
+    XBT_DEBUG("suspend %s", smx_process->name);
+    SIMIX_process_suspend(smx_process, issuer);
   }
-
-  /* TODO: Using the variable of the MSG layer is not clean. */
-  SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_SAVED);
 }
 
-void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm){
-  SIMIX_vm_save(ind_vm);
+void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_save(ind_vm, simcall->issuer);
+
+  /* without this, simcall_vm_suspend() does not return to the userland. why? */
+  SIMIX_simcall_answer(simcall);
 }
 
 
@@ -245,27 +272,29 @@ void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm){
  *
  * \param host the vm host to restore (a smx_host_t)
  */
-void SIMIX_vm_restore(smx_host_t ind_vm)
+void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer)
 {
-  /* TODO: check state */
+  const char *name = SIMIX_host_get_name(ind_vm);
 
-  XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SAVED)
+    THROWF(vm_error, 0, "VM(%s) was not saved", name);
+
+  XBT_DEBUG("restore VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
 
-  /* TODO: do something at the surf level */
+  /* jump to vm_ws_restore() */
+  surf_vm_workstation_model->extension.vm_workstation.resume(ind_vm);
 
   smx_process_t smx_process, smx_process_safe;
   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
-         XBT_DEBUG("restore %s", SIMIX_host_get_name(ind_vm));
-        /* FIXME: calling a simcall from the SIMIX layer is strange. */
-         simcall_process_resume(smx_process);
+    XBT_DEBUG("resume %s", smx_process->name);
+    SIMIX_process_resume(smx_process, issuer);
   }
-
-  /* TODO: Using the variable of the MSG layer is not clean. */
-  SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
 }
 
-void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm){
-  SIMIX_vm_restore(ind_vm);
+void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_restore(ind_vm, simcall->issuer);
+  SIMIX_simcall_answer(simcall);
 }
 
 
@@ -278,23 +307,27 @@ void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm){
  */
 void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer)
 {
-  /* TODO: check state */
+  const char *name = SIMIX_host_get_name(ind_vm);
+
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", name);
 
   XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
 
   smx_process_t smx_process, smx_process_safe;
   xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
-         XBT_DEBUG("kill %s", SIMIX_host_get_name(ind_vm));
-
-        SIMIX_process_kill(smx_process, issuer);
+    XBT_DEBUG("shutdown %s", name);
+    SIMIX_process_kill(smx_process, issuer);
   }
 
-  /* TODO: Using the variable of the MSG layer is not clean. */
+  /* FIXME: we may have to do something at the surf layer, e.g., vcpu action */
   SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_CREATED);
 }
 
-void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm){
-   SIMIX_vm_shutdown(ind_vm, simcall->issuer);
+void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_shutdown(ind_vm, simcall->issuer);
+  SIMIX_simcall_answer(simcall);
 }
 
 
index 82b329f..0509432 100644 (file)
@@ -53,7 +53,7 @@ static void vm_ws_create(const char *name, void *ind_phys_workstation)
    * If you want to get a workstation_VM2013 object from host_lib, see
    * ws->generic_resouce.model->type first. If it is
    * SURF_MODEL_TYPE_VM_WORKSTATION, you can cast ws to vm_ws. */
-  XBT_INFO("Create VM(%s) @ PM(%s) with %ld mounted disks", name, sub_ws_name, xbt_dynar_length(ws->storage));
+  XBT_INFO("Create VM(%s)@PM(%s) with %ld mounted disks", name, sub_ws_name, xbt_dynar_length(ws->storage));
   xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws);
 
 
@@ -83,11 +83,12 @@ static void vm_ws_create(const char *name, void *ind_phys_workstation)
 
 
   /* We create cpu_action corresponding to a VM process on the host operating system. */
-  vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, GUESTOS_NOISE);
+  /* FIXME: TODO: we have to peridocally input GUESTOS_NOISE to the system? how ? */
+  // vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, GUESTOS_NOISE);
+  vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, 0);
 
 
   /* TODO:
-   * - rebind each time you migrate a VM
    * - check how network requests are scheduled between distinct processes competing for the same card.
    */
 }
@@ -95,15 +96,40 @@ static void vm_ws_create(const char *name, void *ind_phys_workstation)
 /*
  * Update the physical host of the given VM
  */
-static void vm_ws_migrate(void *ind_vm_workstation, void *ind_dest_phys_workstation)
+static void vm_ws_migrate(void *ind_vm, void *ind_dst_pm)
 { 
    /* ind_phys_workstation equals to smx_host_t */
-   workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_workstation);
-   xbt_assert(vm_ws);
+   workstation_VM2013_t ws_vm2013 = surf_workstation_resource_priv(ind_vm);
+   workstation_CLM03_t ws_clm03_dst = surf_workstation_resource_priv(ind_dst_pm);
+   const char *vm_name = ws_vm2013->ws.generic_resource.name;
+   const char *pm_name_src = ws_vm2013->sub_ws->generic_resource.name;
+   const char *pm_name_dst = ws_clm03_dst->generic_resource.name;
+
+   xbt_assert(ws_vm2013);
+   xbt_assert(ws_clm03_dst);
+
+   ws_vm2013->current_state = SURF_VM_STATE_MIGRATING;
 
    /* do something */
 
-   vm_ws->sub_ws = surf_workstation_resource_priv(ind_dest_phys_workstation);
+   /* update net_elm with that of the destination physical host */
+   void *old_net_elm = ws_vm2013->ws.net_elm;
+   void *new_net_elm = xbt_lib_get_or_null(host_lib, pm_name_dst, ROUTING_HOST_LEVEL);
+   xbt_assert(new_net_elm);
+
+   /* Unregister the current net_elm from host_lib. Do not call the free callback. */
+   xbt_lib_unset(host_lib, vm_name, ROUTING_HOST_LEVEL, 0);
+
+   /* Then, resister the new one. */
+   ws_vm2013->ws.net_elm = new_net_elm;
+   xbt_lib_set(host_lib, vm_name, ROUTING_HOST_LEVEL, ws_vm2013->ws.net_elm);
+
+   ws_vm2013->sub_ws = ws_clm03_dst;
+
+   XBT_DEBUG("migrate VM(%s): change net_elm (%p to %p)", vm_name, old_net_elm, new_net_elm);
+   XBT_DEBUG("migrate VM(%s): change PM (%s to %s)", vm_name, pm_name_src, pm_name_dst);
+
+   ws_vm2013->current_state = SURF_VM_STATE_RUNNING;
 }
 
 /*
@@ -124,15 +150,12 @@ static void vm_ws_destroy(void *ind_vm_workstation)
        xbt_assert(vm_ws->ws.generic_resource.model == surf_vm_workstation_model);
 
 
-  /* xbt_lib_remove() deletes all entries associated to the VM from host_lib.
-   * This function does not invoke the registered freeing callback of each
-   * level.
+  /* We deregister objects from host_lib, without invoking the freeing callback
+   * of each level.
    *
-   * FIXME: But, this function deletes all levels of the key. We must
-   * be sure that there is no entry at any level. */
-       // xbt_lib_remove(host_lib, name);
-       // Remove all others in the lib associated to the VM
-  // Please note that you only remove the entries (and not free them)
+   * Do not call xbt_lib_remove() here. It deletes all levels of the key,
+   * including MSG_HOST_LEVEL and others. We should unregister only what we know.
+   */
   xbt_lib_unset(host_lib, name, SURF_CPU_LEVEL, 0);
   xbt_lib_unset(host_lib, name, ROUTING_HOST_LEVEL, 0);
   xbt_lib_unset(host_lib, name, SURF_STORAGE_LEVEL, 0);
@@ -159,12 +182,57 @@ static void vm_ws_destroy(void *ind_vm_workstation)
   surf_resource_free(vm_ws);
 }
 
-static int vm_ws_get_state(void *ind_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 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 vm_ws_suspend(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  XBT_INFO("vm %p suspend", ind_vm_ws);
+  surf_action_suspend(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_SUSPENDED;
+}
+
+static void vm_ws_resume(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  surf_action_resume(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_RUNNING;
+}
+
+static void vm_ws_save(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  vm_ws->current_state = SURF_VM_STATE_SAVING;
+
+  /* FIXME: do something here */
+  surf_action_suspend(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_SAVED;
+}
+
+static void vm_ws_restore(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  vm_ws->current_state = SURF_VM_STATE_RESTORING;
+
+  /* FIXME: do something here */
+  surf_action_resume(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_RUNNING;
 }
 
 
@@ -281,8 +349,19 @@ static double vm_ws_share_resources(surf_model_t workstation_model, double now)
     workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
     {
       void *ind_sub_host = xbt_lib_get_elm_or_null(host_lib, ws_vm2013->sub_ws->generic_resource.name);
+      XBT_INFO("cost %f remains %f start %f finish %f", ws_vm2013->cpu_action->cost,
+          ws_vm2013->cpu_action->remains,
+          ws_vm2013->cpu_action->start,
+          ws_vm2013->cpu_action->finish
+          );
+
+#if 0
       surf_cpu_model_pm->action_unref(ws_vm2013->cpu_action);
-      ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, 100); // cost 0 is okay?
+      /* FIXME: this means busy loop? */
+      // ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, GUESTOS_NOISE);
+      ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, 0);
+#endif
+
     }
   }
 #endif
@@ -293,23 +372,56 @@ static double vm_ws_share_resources(surf_model_t workstation_model, double now)
 
 
 /*
- * A surf level object will be useless in the upper layer. Returing the name
- * will be simple and suffcient.
+ * A surf level object will be useless in the upper layer. Returing the
+ * dict_elm of the host.
  **/
-static const char *vm_ws_get_phys_host(void *ind_vm_ws)
+static void *vm_ws_get_pm(void *ind_vm_ws)
 {
        workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
-       return vm_ws->sub_ws->generic_resource.name;
+  const char *sub_ws_name = vm_ws->sub_ws->generic_resource.name;
+
+  return xbt_lib_get_elm_or_null(host_lib, sub_ws_name);
+}
+
+
+
+/* Adding a task to a VM updates the VCPU task on its physical machine. */
+surf_action_t vm_ws_execute(void *workstation, double size)
+{
+  surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(workstation));
+
+  xbt_assert(ws->model->type == SURF_MODEL_TYPE_VM_WORKSTATION);
+  workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+  double old_cost = vm_ws->cpu_action->cost;
+  double new_cost = old_cost + size;
+
+  XBT_INFO("VM(%s)@PM(%s): update dummy action's cost (%f -> %f)",
+      ws->name, vm_ws->sub_ws->generic_resource.name,
+      old_cost, new_cost);
+
+  vm_ws->cpu_action->cost = new_cost;
+
+  return ws_execute(workstation, size);
 }
 
+static void vm_ws_action_cancel(surf_action_t action)
+{
+  XBT_CRITICAL("FIXME: Not yet implemented. Reduce dummy action's cost by %f", action->cost);
+
+  ws_action_cancel(action);
+}
+
+
 static void surf_vm_workstation_model_init_internal(void)
 {
   surf_model_t model = surf_model_init();
 
   model->name = "Virtual Workstation";
   model->type = SURF_MODEL_TYPE_VM_WORKSTATION;
+
   // model->action_unref     = ws_action_unref;
-  // model->action_cancel    = ws_action_cancel;
+  model->action_cancel    = vm_ws_action_cancel;
   // model->action_state_set = ws_action_state_set;
 
 
@@ -320,8 +432,9 @@ static void surf_vm_workstation_model_init_internal(void)
   model->model_private->finalize              = ws_finalize;
 
 
-//   model->suspend          = ws_action_suspend;
-//   model->resume           = ws_action_resume;
+  /* operation for an action, not for VM it self */
+  model->suspend          = ws_action_suspend;
+  model->resume           = ws_action_resume;
 //   model->is_suspended     = ws_action_is_suspended;
 //   model->set_max_duration = ws_action_set_max_duration;
   model->set_priority     = ws_action_set_priority;
@@ -342,8 +455,8 @@ static void surf_vm_workstation_model_init_internal(void)
   xbt_assert(surf_cpu_model_vm);
   model->extension.workstation.cpu_model = surf_cpu_model_vm;
 
-  model->extension.workstation.execute   = ws_execute;
-  // model->extension.workstation.sleep     = ws_action_sleep;
+  model->extension.workstation.execute   = vm_ws_execute;
+  model->extension.workstation.sleep     = ws_action_sleep;
   model->extension.workstation.get_state = ws_get_state;
   // model->extension.workstation.get_speed = ws_get_speed;
   // model->extension.workstation.get_available_speed = ws_get_available_speed;
@@ -369,8 +482,12 @@ static void surf_vm_workstation_model_init_internal(void)
   model->extension.vm_workstation.set_state     = vm_ws_set_state;
   model->extension.vm_workstation.get_state     = vm_ws_get_state;
   model->extension.vm_workstation.migrate       = vm_ws_migrate;
-  model->extension.vm_workstation.get_phys_host = vm_ws_get_phys_host;
+  model->extension.vm_workstation.get_pm        = vm_ws_get_pm;
   model->extension.vm_workstation.destroy       = vm_ws_destroy;
+  model->extension.vm_workstation.suspend       = vm_ws_suspend;
+  model->extension.vm_workstation.resume        = vm_ws_resume;
+  model->extension.vm_workstation.save          = vm_ws_save;
+  model->extension.vm_workstation.restore       = vm_ws_restore;
 
   surf_vm_workstation_model = model;
 }
index 327c1a8..e00df15 100644 (file)
@@ -46,7 +46,7 @@ static int ws_parallel_action_free(surf_action_t action)
   return -1;
 }
 
-static int ws_action_unref(surf_action_t action)
+int ws_action_unref(surf_action_t action)
 {
   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     return surf_network_model->action_unref(action);
@@ -61,7 +61,7 @@ static int ws_action_unref(surf_action_t action)
   return 0;
 }
 
-static void ws_action_cancel(surf_action_t action)
+void ws_action_cancel(surf_action_t action)
 {
   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->action_cancel(action);
@@ -146,13 +146,13 @@ surf_action_t ws_execute(void *workstation, double size)
   return cpu->model->extension.cpu.execute(workstation, size);
 }
 
-static surf_action_t ws_action_sleep(void *workstation, double duration)
+surf_action_t ws_action_sleep(void *workstation, double duration)
 {
   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
   return cpu->model->extension.cpu.sleep(workstation, duration);
 }
 
-static void ws_action_suspend(surf_action_t action)
+void ws_action_suspend(surf_action_t action)
 {
   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->suspend(action);
@@ -162,7 +162,7 @@ static void ws_action_suspend(surf_action_t action)
     DIE_IMPOSSIBLE;
 }
 
-static void ws_action_resume(surf_action_t action)
+void ws_action_resume(surf_action_t action)
 {
   if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->resume(action);
index 017f847..5b63d3f 100644 (file)
@@ -22,5 +22,8 @@ void ws_finalize(surf_model_t workstation_model);
 void ws_action_set_priority(surf_action_t action, double priority);
 
 surf_action_t ws_execute(void *workstation, double size);
+surf_action_t ws_action_sleep(void *workstation, double duration);
+void ws_action_suspend(surf_action_t action);
+void ws_action_resume(surf_action_t action);
 e_surf_resource_state_t ws_get_state(void *workstation);
 #endif /* WS_PRIVATE_H_ */