X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/ce06185a3d18128e760608e10a5885793d56ac9b..4e78565ea6b354a0e6250a87b483f909665a0ac3:/src/surf/vm_workstation.c diff --git a/src/surf/vm_workstation.c b/src/surf/vm_workstation.c index 94933ebd1e..36964dcb14 100644 --- a/src/surf/vm_workstation.c +++ b/src/surf/vm_workstation.c @@ -10,48 +10,130 @@ #include "surf_private.h" #include "surf/surf_resource.h" #include "simgrid/sg_config.h" +#include "workstation_private.h" +#include "surf/cpu_cas01_private.h" +#include "surf/maxmin_private.h" + +/* NOTE: + * The workstation_VM2013 struct includes the workstation_CLM03 struct in + * its first member. The workstation_VM2013_t struct inherites all + * characteristics of the workstation_CLM03 struct. So, we can treat a + * workstation_VM2013 object as a workstation_CLM03 if necessary. + **/ 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_CLM03_t ws; /* a VM is a ''v''host */ + + /* The workstation object of the lower layer */ + workstation_CLM03_t sub_ws; // Pointer to the ''host'' OS + + e_surf_vm_state_t current_state; + + + surf_action_t cpu_action; + } 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); + + vm_ws->sub_ws = surf_workstation_resource_priv(ind_phys_workstation); + vm_ws->current_state = SURF_VM_STATE_CREATED; + + + // //// WORKSTATION RELATED STUFF //// + /* Create a workstation_CLM03 resource and register it to the system + Please note that the new ws is added into the host_lib. Then, + 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. */ + + __init_workstation_CLM03(&vm_ws->ws, name); + + // Override the model with the current VM one. + vm_ws->ws.generic_resource.model = surf_vm_workstation_model; + + + // //// CPU RELATED STUFF //// + // Roughly, create a vcpu resource by using the values of the sub_cpu one. + cpu_Cas01_t sub_cpu = surf_cpu_resource_priv(ind_phys_workstation); + + /* We can assume one core and cas01 cpu for the first step. + * Do xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu) if you get the resource. + * */ + cpu_cas01_create_resource(name, // name + sub_cpu->power_peak, // host->power_peak, + 1, // host->power_scale, + NULL, // host->power_trace, + 1, // host->core_amount, + SURF_RESOURCE_ON, // host->initial_state, + NULL, // host->state_trace, + NULL, // host->properties, + surf_cpu_model_vm); + + vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, 100); // cost 0 is okay? + + //// NET RELATED STUFF //// + // Bind virtual net_elm to the host + // TODO rebind each time you migrate a VM + // TODO check how network requests are scheduled between distinct processes competing for the same card. + // Please note that the __init_workstation_CLM03 invocation assigned NULL to ws.net_elm since no network elements + // were previously created for this hostname. Indeed all network elements are created during the SimGrid initialization phase by considering + // the platform file. + vm_ws->ws.net_elm = xbt_lib_get_or_null(host_lib, vm_ws->sub_ws->generic_resource.name, ROUTING_HOST_LEVEL); + xbt_lib_set(host_lib, name, ROUTING_HOST_LEVEL, vm_ws->ws.net_elm); + + // //// STORAGE RELATED STUFF //// // 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); + + } +/* + * Update the physical host of the given VM + */ +static void vm_ws_migrate(void *ind_vm_workstation, void *ind_dest_phys_workstation) +{ + /* ind_phys_workstation equals to smx_host_t */ + workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_workstation); + xbt_assert(vm_ws); + + /* do something */ + + vm_ws->sub_ws = surf_workstation_resource_priv(ind_dest_phys_workstation); +} /* * 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) +static void vm_ws_destroy(void *ind_vm_workstation) { /* ind_phys_workstation equals to smx_host_t */ - workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_phys_workstation); + workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_workstation); xbt_assert(vm_ws); - xbt_assert(vm_ws->generic_resource.model == surf_vm_workstation_model); + xbt_assert(vm_ws->ws.generic_resource.model == surf_vm_workstation_model); + + { + int ret = surf_cpu_model_pm->action_unref(vm_ws->cpu_action); + xbt_assert(ret == 1, "Bug: some resource still remains"); + } - const char *name = vm_ws->generic_resource.name; + const char *name = vm_ws->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); + /* NOTE: surf_resource_free() frees vm_ws->ws.generic_resource.name and + * vm_ws->ws. Do not free them here. */ } static int vm_ws_get_state(void *ind_vm_ws){ @@ -61,21 +143,214 @@ static int vm_ws_get_state(void *ind_vm_ws){ 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 double get_solved_value(surf_action_t cpu_action) +{ + int found = 0; + /* NOTE: Do not use surf_workstation_model's maxmin_system. It is not used. */ + lmm_system_t pm_system = surf_cpu_model_pm->model_private->maxmin_system; + lmm_variable_t var = NULL; + + xbt_swag_foreach(var, &pm_system->variable_set) { + XBT_DEBUG("var id %p id_int %d double %f", var->id, var->id_int, var->value); + if (var->id == cpu_action) { + found = 1; + break; + } + } + + if (found) + return var->value; + + XBT_CRITICAL("bug: cannot found the solved variable of the action %p", cpu_action); + DIE_IMPOSSIBLE; + return -1; /* NOT REACHED */ +} + + +static double vm_ws_share_resources(surf_model_t workstation_model, double now) +{ + /* 0. Make sure that we already calculated the resource share at the physical + * machine layer. */ + { + unsigned int index_of_pm_ws_model = xbt_dynar_search(model_list_invoke, &surf_workstation_model); + unsigned int index_of_vm_ws_model = xbt_dynar_search(model_list_invoke, &surf_vm_workstation_model); + xbt_assert((index_of_pm_ws_model < index_of_vm_ws_model), "Cannot assume surf_workstation_model comes before"); + + /* Another option is that we call sub_ws->share_resource() here. The + * share_resource() function has no side-effect. We can call it here to + * ensure that. */ + } + + + /* 1. Now we know how many resource should be assigned to each virtual + * machine. We update constraints of the virtual machine layer. + * + * + * If we have two virtual machine (VM1 and VM2) on a physical machine (PM1). + * X1 + X2 = C (Equation 1) + * where + * the resource share of VM1: X1 + * the resource share of VM2: X2 + * the capacity of PM1: C + * + * Then, if we have two process (P1 and P2) on VM1. + * X1_1 + X1_2 = X1 (Equation 2) + * where + * the resource share of P1: X1_1 + * the resource share of P2: X1_2 + * the capacity of VM1: X1 + * + * Equation 1 was solved in the physical machine layer. + * Equation 2 is solved in the virtual machine layer (here). + * X1 must be passed to the virtual machine laye as a constraint value. + * + **/ + + /* iterate for all hosts including virtual machines */ + xbt_lib_cursor_t cursor; + char *key; + void **ind_host; + xbt_lib_foreach(host_lib, cursor, key, ind_host) { + workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL]; + cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL]; + + /* skip if it is not a virtual machine */ + if (!ws_clm03) + continue; + if (ws_clm03->generic_resource.model != surf_vm_workstation_model) + continue; + xbt_assert(cpu_cas01, "cpu-less workstation"); + + /* It is a virtual machine, so we can cast it to workstation_VM2013_t */ + workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03; + + double solved_value = get_solved_value(ws_vm2013->cpu_action); + XBT_DEBUG("assign %f to vm %s @ pm %s", solved_value, + ws_clm03->generic_resource.name, ws_vm2013->sub_ws->generic_resource.name); + + cpu_cas01->constraint->bound = solved_value; + } + + + /* 2. Calculate resource share at the virtual machine layer. */ + double ret = ws_share_resources(workstation_model, now); + + + /* FIXME: 3. do we have to re-initialize our cpu_action object? */ +#if 1 + /* iterate for all hosts including virtual machines */ + xbt_lib_foreach(host_lib, cursor, key, ind_host) { + workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL]; + + /* skip if it is not a virtual machine */ + if (!ws_clm03) + continue; + if (ws_clm03->generic_resource.model != surf_vm_workstation_model) + continue; + + /* It is a virtual machine, so we can cast it to workstation_VM2013_t */ + 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); + 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? + } + } +#endif + + + return ret; +} + + +/* + * A surf level object will be useless in the upper layer. Returing the name + * will be simple and suffcient. + **/ +static const char *vm_ws_get_phys_host(void *ind_vm_ws) +{ + workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws); + return vm_ws->sub_ws->generic_resource.name; +} + static void surf_vm_workstation_model_init_internal(void) { - surf_vm_workstation_model = surf_model_init(); + 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_state_set = ws_action_state_set; + + + model->model_private->share_resources = vm_ws_share_resources; + model->model_private->resource_used = ws_resource_used; + model->model_private->update_actions_state = ws_update_actions_state; + model->model_private->update_resource_state = ws_update_resource_state; + model->model_private->finalize = ws_finalize; + + +// 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; +// #ifdef HAVE_TRACING +// model->set_category = ws_action_set_category; +// #endif +// model->get_remains = ws_action_get_remains; +// #ifdef HAVE_LATENCY_BOUND_TRACKING +// model->get_latency_limited = ws_get_latency_limited; +// #endif + + + + + + + + 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.get_state = ws_get_state; + // model->extension.workstation.get_speed = ws_get_speed; + // model->extension.workstation.get_available_speed = ws_get_available_speed; + + // model->extension.workstation.communicate = ws_communicate; + // model->extension.workstation.get_route = ws_get_route; + // model->extension.workstation.execute_parallel_task = ws_execute_parallel_task; + // model->extension.workstation.get_link_bandwidth = ws_get_link_bandwidth; + // model->extension.workstation.get_link_latency = ws_get_link_latency; + // model->extension.workstation.link_shared = ws_link_shared; + // model->extension.workstation.get_properties = ws_get_properties; + + // model->extension.workstation.open = ws_action_open; + // model->extension.workstation.close = ws_action_close; + // model->extension.workstation.read = ws_action_read; + // model->extension.workstation.write = ws_action_write; + // model->extension.workstation.stat = ws_action_stat; + // model->extension.workstation.unlink = ws_action_unlink; + // model->extension.workstation.ls = ws_action_ls; - 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; + model->extension.vm_workstation.create = vm_ws_create; + 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.destroy = vm_ws_destroy; + surf_vm_workstation_model = model; } void surf_vm_workstation_model_init() { surf_vm_workstation_model_init_internal(); xbt_dynar_push(model_list, &surf_vm_workstation_model); + xbt_dynar_push(model_list_invoke, &surf_vm_workstation_model); }