diff --git a/slurm/slurm.h.in b/slurm/slurm.h.in index 038c1839de999a0f1eb6cb744dec2429e22e4d17..605de6caa85c97e77bafd7c038c89a25b4a66bff 100644 --- a/slurm/slurm.h.in +++ b/slurm/slurm.h.in @@ -2392,18 +2392,19 @@ typedef struct trigger_info_msg { /* Individual license information */ typedef struct slurm_license_info { - char *feature; /* feature name */ + char *name; /* license name */ uint32_t total; /* total number of available licenses */ uint32_t in_use; /* number of license in use */ uint32_t available; /* number of available license */ - uint32_t cluster; /* non-zero if cluster license */ + uint8_t remote; /* non-zero if remote license (not + * defined in slurm.conf) */ } slurm_license_info_t; /* License information array as returned by the controller. */ typedef struct license_info_msg { time_t last_update; - uint32_t num_features; + uint32_t num_lic; slurm_license_info_t *lic_array; } license_info_msg_t; diff --git a/slurm/slurmdb.h b/slurm/slurmdb.h index d883dd7456ff5915e0b58d8334cfdf497113e636..1e4c2688a8d44387e308dc5a63b5b9eb74e7bc26 100644 --- a/slurm/slurmdb.h +++ b/slurm/slurmdb.h @@ -112,7 +112,8 @@ typedef enum { } slurmdb_report_time_format_t; typedef enum { - SLURMDB_RESOURCE_LICENSE = 1, + SLURMDB_RESOURCE_NOTSET, + SLURMDB_RESOURCE_LICENSE, } slurmdb_resource_type_t; typedef enum { diff --git a/src/common/assoc_mgr.c b/src/common/assoc_mgr.c index 41ecdc7ee7198c615a8bba3bf936716873de4421..cd6be8685d2d7b72c73cb1b956c20791b05af412 100644 --- a/src/common/assoc_mgr.c +++ b/src/common/assoc_mgr.c @@ -62,9 +62,13 @@ static char *assoc_mgr_cluster_name = NULL; static int setup_children = 0; static assoc_mgr_lock_flags_t assoc_mgr_locks; +void (*add_license_notify) (slurmdb_clus_res_rec_t *rec) = NULL; void (*remove_assoc_notify) (slurmdb_association_rec_t *rec) = NULL; +void (*remove_license_notify) (slurmdb_clus_res_rec_t *rec) = NULL; void (*remove_qos_notify) (slurmdb_qos_rec_t *rec) = NULL; +void (*sync_license_notify) (List clus_res_list) = NULL; void (*update_assoc_notify) (slurmdb_association_rec_t *rec) = NULL; +void (*update_license_notify) (slurmdb_clus_res_rec_t *rec) = NULL; void (*update_qos_notify) (slurmdb_qos_rec_t *rec) = NULL; void (*update_resvs) () = NULL; @@ -665,6 +669,14 @@ static int _post_qos_list(List qos_list) return SLURM_SUCCESS; } +static int _post_clus_res_list(List clus_res_list) +{ + if (sync_license_notify) + sync_license_notify(clus_res_list); + + return SLURM_SUCCESS; +} + static int _get_assoc_mgr_association_list(void *db_conn, int enforce) { slurmdb_association_cond_t assoc_q; @@ -729,7 +741,7 @@ static int _get_assoc_mgr_clus_res_list(void *db_conn, int enforce) if (assoc_mgr_clus_res_list) list_destroy(assoc_mgr_clus_res_list); assoc_mgr_clus_res_list = - acct_storage_g_get_clus_res(db_conn, uid, NULL); + acct_storage_g_get_clus_res(db_conn, uid, NULL); if (!assoc_mgr_clus_res_list) { assoc_mgr_unlock(&locks); @@ -742,7 +754,7 @@ static int _get_assoc_mgr_clus_res_list(void *db_conn, int enforce) } } -// _post_clus_res_list(assoc_mgr_clus_res_list); + _post_clus_res_list(assoc_mgr_clus_res_list); assoc_mgr_unlock(&locks); return SLURM_SUCCESS; @@ -961,7 +973,7 @@ static int _refresh_assoc_mgr_clus_res_list(void *db_conn, int enforce) "no new list given back keeping cached one."); return SLURM_ERROR; } -// _post_clus_res_list(current_clus_res); + _post_clus_res_list(current_clus_res); assoc_mgr_lock(&locks); @@ -1170,12 +1182,20 @@ extern int assoc_mgr_init(void *db_conn, assoc_init_args_t *args, cache_level = args->cache_level; enforce = args->enforce; + if (args->add_license_notify) + add_license_notify = args->add_license_notify; if (args->remove_assoc_notify) remove_assoc_notify = args->remove_assoc_notify; + if (args->remove_license_notify) + remove_license_notify = args->remove_license_notify; if (args->remove_qos_notify) remove_qos_notify = args->remove_qos_notify; + if (args->sync_license_notify) + sync_license_notify = args->sync_license_notify; if (args->update_assoc_notify) update_assoc_notify = args->update_assoc_notify; + if (args->update_license_notify) + update_license_notify = args->update_license_notify; if (args->update_qos_notify) update_qos_notify = args->update_qos_notify; if (args->update_resvs) @@ -3313,6 +3333,16 @@ extern int assoc_mgr_update_clus_res(slurmdb_update_object_t *update) } list_append(assoc_mgr_clus_res_list, object); + switch (object->res_ptr->type) { + case SLURMDB_RESOURCE_LICENSE: + if (add_license_notify) + add_license_notify(object); + break; + default: + error("SLURMDB_ADD_CLUS_RES: unknown type %d", + object->res_ptr->type); + break; + } object = NULL; break; case SLURMDB_MODIFY_CLUS_RES: @@ -3323,12 +3353,34 @@ extern int assoc_mgr_update_clus_res(slurmdb_update_object_t *update) if (object->percent_allowed != NO_VAL) rec->percent_allowed = object->percent_allowed; + switch (rec->res_ptr->type) { + case SLURMDB_RESOURCE_LICENSE: + if (update_license_notify) + update_license_notify(rec); + break; + default: + error("SLURMDB_UPDATE_CLUS_RES: " + "unknown type %d", + rec->res_ptr->type); + break; + } break; case SLURMDB_REMOVE_CLUS_RES: if (!rec) { //rc = SLURM_ERROR; break; } + switch (rec->res_ptr->type) { + case SLURMDB_RESOURCE_LICENSE: + if (remove_license_notify) + remove_license_notify(rec); + break; + default: + error("SLURMDB_REMOVE_CLUS_RES: " + "unknown type %d", + object->res_ptr->type); + break; + } list_delete_item(itr); break; @@ -4045,6 +4097,7 @@ extern int load_assoc_mgr_state(char *state_save_location) if (assoc_mgr_clus_res_list) list_destroy(assoc_mgr_clus_res_list); assoc_mgr_clus_res_list = msg->my_list; + _post_clus_res_list(assoc_mgr_clus_res_list); debug("Recovered %u clus_res", list_count(assoc_mgr_clus_res_list)); msg->my_list = NULL; @@ -4136,9 +4189,8 @@ extern int assoc_mgr_refresh_lists(void *db_conn, assoc_init_args_t *args) return SLURM_ERROR; if (cache_level & ASSOC_MGR_CACHE_CLUS_RES) -info("invoking _refresh_assoc_mgr_clus_res_list"); if (_refresh_assoc_mgr_clus_res_list(db_conn, enforce) - ==SLURM_ERROR) + == SLURM_ERROR) return SLURM_ERROR; running_cache = 0; diff --git a/src/common/assoc_mgr.h b/src/common/assoc_mgr.h index 311c7d568e30620afc8b3d1f2860f1c2d1f3c81e..b37711880c933e501b4f95f776b9a47c6a755ce4 100644 --- a/src/common/assoc_mgr.h +++ b/src/common/assoc_mgr.h @@ -93,9 +93,13 @@ typedef struct { typedef struct { uint16_t cache_level; uint16_t enforce; + void (*add_license_notify) (slurmdb_clus_res_rec_t *rec); void (*remove_assoc_notify) (slurmdb_association_rec_t *rec); + void (*remove_license_notify) (slurmdb_clus_res_rec_t *rec); void (*remove_qos_notify) (slurmdb_qos_rec_t *rec); + void (*sync_license_notify) (List clus_res_list); void (*update_assoc_notify) (slurmdb_association_rec_t *rec); + void (*update_license_notify) (slurmdb_clus_res_rec_t *rec); void (*update_qos_notify) (slurmdb_qos_rec_t *rec); void (*update_resvs) (); } assoc_init_args_t; diff --git a/src/common/slurm_protocol_defs.c b/src/common/slurm_protocol_defs.c index 8d6b05f232a82a2d07f9c99fb1f45e8248b2fd1c..7079880db3bae1bf03f6bb134797c87b3b696318 100644 --- a/src/common/slurm_protocol_defs.c +++ b/src/common/slurm_protocol_defs.c @@ -2953,8 +2953,8 @@ slurm_free_license_info_msg(license_info_msg_t *msg) if (msg == NULL) return; - for (cc = 0; cc < msg->num_features; cc++) { - xfree(msg->lic_array[cc].feature); + for (cc = 0; cc < msg->num_lic; cc++) { + xfree(msg->lic_array[cc].name); } xfree(msg->lic_array); xfree(msg); diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c index 722f512a50a3f67fd79a5ca86da395ca2ddbfe39..ad880941a309afb93f5269693e754f48c4833808 100644 --- a/src/common/slurm_protocol_pack.c +++ b/src/common/slurm_protocol_pack.c @@ -11722,23 +11722,24 @@ _unpack_license_info_msg(license_info_msg_t **msg, */ if (protocol_version >= SLURM_14_03_PROTOCOL_VERSION) { - safe_unpack32(&((*msg)->num_features), buffer); + safe_unpack32(&((*msg)->num_lic), buffer); safe_unpack_time(&((*msg)->last_update), buffer); (*msg)->lic_array = xmalloc(sizeof(slurm_license_info_t) - * (*msg)->num_features); + * (*msg)->num_lic); /* Decode individual license data. */ - for (i = 0; i < (*msg)->num_features; i++) { - - safe_unpackstr_xmalloc(&((*msg)->lic_array[i]).feature, &zz, buffer); + for (i = 0; i < (*msg)->num_lic; i++) { + safe_unpackstr_xmalloc(&((*msg)->lic_array[i]).name, + &zz, buffer); safe_unpack32(&((*msg)->lic_array[i]).total, buffer); safe_unpack32(&((*msg)->lic_array[i]).in_use, buffer); - (*msg)->lic_array[i].available - = (*msg)->lic_array[i].total - (*msg)->lic_array[i].in_use; + (*msg)->lic_array[i].available = + (*msg)->lic_array[i].total - + (*msg)->lic_array[i].in_use; xassert((*msg)->lic_array[i].available >= 0); - safe_unpack32(&((*msg)->lic_array[i]).cluster, buffer); + safe_unpack8(&((*msg)->lic_array[i]).remote, buffer); } } else { diff --git a/src/scontrol/info_lics.c b/src/scontrol/info_lics.c index 906c792a8e6b6ee0a6087fd2e3a6303cce78d3de..a027002013af85a9cdfea6a96a6b0b9a4c9cf691 100644 --- a/src/scontrol/info_lics.c +++ b/src/scontrol/info_lics.c @@ -40,8 +40,7 @@ #include "scontrol.h" -static void print_license_info(const char *, - struct license_info_msg *); +static void _print_license_info(const char *, license_info_msg_t *); /* scontrol_print_licenses() * @@ -50,10 +49,10 @@ static void print_license_info(const char *, * */ void -scontrol_print_licenses(const char *feature) +scontrol_print_licenses(const char *name) { int cc; - struct license_info_msg *msg; + license_info_msg_t *msg; uint16_t show_flags; static time_t last_update; @@ -73,7 +72,7 @@ scontrol_print_licenses(const char *feature) last_update = time(NULL); /* print the info */ - print_license_info(feature, msg); + _print_license_info(name, msg); /* free at last */ @@ -82,33 +81,30 @@ scontrol_print_licenses(const char *feature) return; } -/* print_license_info() +/* _print_license_info() * * Print the license information. */ -static void -print_license_info(const char *feature, struct license_info_msg *msg) +static void _print_license_info(const char *name, license_info_msg_t *msg) { int cc; - if (msg->num_features == 0) { - printf("No licenses configured in SLURM.\n"); + if (!msg->num_lic) { + printf("No licenses configured in Slurm.\n"); return; } - for (cc = 0; cc < msg->num_features; cc++) { - if (one_liner) { - printf("LicenseName=%s ", msg->lic_array[cc].feature); - printf("Total=%d ", msg->lic_array[cc].total); - } else { - printf("LicenseName=%s\n", msg->lic_array[cc].feature); - printf(" Total=%d ", msg->lic_array[cc].total); - } - printf("Used=%d ", msg->lic_array[cc].in_use); - printf("Free=%d ", msg->lic_array[cc].available); - if (msg->lic_array[cc].cluster) - printf("Cluster=yes\n"); - else - printf("Cluster=no\n"); + for (cc = 0; cc < msg->num_lic; cc++) { + if (name && strcmp(msg->lic_array[cc].name, name)) + continue; + printf("LicenseName=%s%sTotal=%d Used=%u Free=%u Remote=%s\n", + msg->lic_array[cc].name, + one_liner ? " " : "\n ", + msg->lic_array[cc].total, + msg->lic_array[cc].in_use, + msg->lic_array[cc].available, + msg->lic_array[cc].remote ? "yes" : "no"); + if (name) + break; } } diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c index 6f79ef60d97544321451fb5b884430e7311ba848..3b98b89b45fce77a8292bebbdd73f93b752598e2 100644 --- a/src/slurmctld/controller.c +++ b/src/slurmctld/controller.c @@ -370,11 +370,15 @@ int main(int argc, char *argv[]) memset(&assoc_init_arg, 0, sizeof(assoc_init_args_t)); assoc_init_arg.enforce = accounting_enforce; - assoc_init_arg.update_resvs = update_assocs_in_resvs; + assoc_init_arg.add_license_notify = license_add_remote; assoc_init_arg.remove_assoc_notify = _remove_assoc; + assoc_init_arg.remove_license_notify = license_remove_remote; assoc_init_arg.remove_qos_notify = _remove_qos; + assoc_init_arg.sync_license_notify = license_sync_remote; assoc_init_arg.update_assoc_notify = _update_assoc; + assoc_init_arg.update_license_notify = license_update_remote; assoc_init_arg.update_qos_notify = _update_qos; + assoc_init_arg.update_resvs = update_assocs_in_resvs; assoc_init_arg.cache_level = ASSOC_MGR_CACHE_ASSOC | ASSOC_MGR_CACHE_USER | ASSOC_MGR_CACHE_QOS | diff --git a/src/slurmctld/licenses.c b/src/slurmctld/licenses.c index 1f3ac3466c3b47b4af0671b58c472040fe389f91..af6d045f71f01e41a35f4c03bb140cabb3394bd3 100644 --- a/src/slurmctld/licenses.c +++ b/src/slurmctld/licenses.c @@ -56,8 +56,7 @@ #include "src/common/slurm_accounting_storage.h" List license_list = (List) NULL; -List clus_license_list = (List) NULL; -time_t last_license_update; +time_t last_license_update = 0; static pthread_mutex_t license_mutex = PTHREAD_MUTEX_INITIALIZER; static void _pack_license(struct licenses *lic, Buf buffer, uint16_t protocol_version); @@ -109,34 +108,6 @@ static int _license_find_rec(void *x, void *key) return 1; } -/* Find a slurmdb_ser_res_rec_t record by license name - *(for use by list_find_first) */ -static int _license_find_sys_rec(void *x, void *key) -{ - slurmdb_ser_res_rec_t *license_entry = (slurmdb_ser_res_rec_t *) x; - char *name = (char *) key; - - if ((license_entry->name == NULL) || (name == NULL)) - return 0; - if (strcmp(license_entry->name, name)) - return 0; - return 1; -} - -/* Find a slurmdb_clus_res_rec_t record by license name - *(for use by list_find_first) */ -static int _license_find_clus_rec(void *x, void *key) -{ - slurmdb_clus_res_rec_t *license_entry = (slurmdb_clus_res_rec_t *) x; - char *name = (char *) key; - - if ((license_entry->res_ptr->name == NULL) || (name == NULL)) - return 0; - if (strcmp(license_entry->res_ptr->name, name)) - return 0; - return 1; -} - /* Given a license string, return a list of license_t records */ static List _build_license_list(char *licenses, bool *valid) { @@ -221,6 +192,21 @@ static char * _build_license_string(List license_list) return licenses; } +/* license_mutex should be locked before alling this. */ +static void _add_clus_rec_2_lic_list(slurmdb_clus_res_rec_t *rec, bool sync) +{ + licenses_t *license_entry = xmalloc(sizeof(licenses_t)); + /* Should we concat the server and such here + * with the name? */ + license_entry->name = xstrdup(rec->res_ptr->name); + license_entry->total = ((rec->res_ptr->count * + rec->percent_allowed) / 100); + license_entry->remote = sync ? 2 : 1; + + list_push(license_list, license_entry); + last_license_update = time(NULL); +} + /* Get string of used license information. Caller must xfree return value */ extern char *get_licenses_used(void) { @@ -245,276 +231,6 @@ extern char *get_licenses_used(void) return licenses_used; } -/* Merge a cluster license list (built using accounting database information - * into a license_list, preserving all previously allocated licenses. -*/ -static List merge_license_lists(List lic_list, List clus_license_list) -{ - licenses_t *license, *cluster_license, *new_license; - ListIterator itr = NULL; - licenses_t *match_lic = NULL; - uint16_t temp; - - if (!clus_license_list) - return lic_list; - if (!license_list) - return clus_license_list; - /* deal with new & potentially modified cluster licenses */ - itr = list_iterator_create(clus_license_list); - while ((cluster_license = list_next(itr))){ - match_lic = list_find_first(license_list, - _license_find_rec, cluster_license->name); - - if (match_lic == NULL) { /* new license */ - new_license = xmalloc(sizeof(licenses_t)); - new_license->name = xstrdup(cluster_license->name); - new_license->total = cluster_license->total; - new_license->used = 0; - new_license->cluster = 1; - list_push(lic_list, new_license); - } else if ((match_lic != NULL) - && cluster_license->cluster == 1) { - match_lic->total = cluster_license->total; - } - } - list_iterator_destroy(itr); - - /* now deal with deleted cluster licenses */ - itr = list_iterator_create(license_list); - while ((license = (licenses_t *) list_next(itr))) { - match_lic = list_find_first(clus_license_list, - _license_find_rec, license->name); - - if ((match_lic == NULL) && (license->cluster == 1)) { - temp = list_delete_item(itr); - if (!temp) - return NULL; - } - } - list_iterator_destroy(itr); - return lic_list; -} - -/* update clus_license_list & license_list for a modified system license */ -static int _modify_ser_lic(List clus_license_list, List clus_rec_list, - slurmdb_update_object_t *update_obj) -{ - ListIterator itr = NULL; - slurmdb_ser_res_rec_t *match_sys_rec = NULL; - slurmdb_clus_res_rec_t *match_clus_rec = NULL; - licenses_t *license; - uint16_t rc = SLURM_SUCCESS; - - itr = list_iterator_create(clus_license_list); - while ((license = list_next(itr))) { - match_sys_rec = list_find_first(update_obj->objects, - _license_find_sys_rec, license->name); - if (match_sys_rec) { - match_clus_rec = list_find_first(clus_rec_list, - _license_find_clus_rec, license->name); - if (match_clus_rec) { - license->total = - ((match_sys_rec->count * - match_clus_rec->percent_allowed) / 100); - } - } - } - list_iterator_destroy(itr); - return rc; -} - -/* update clus_license_list to add a cluster license */ -static int _add_clus_lic(List clus_license_list, - slurmdb_update_object_t *update_obj) -{ - ListIterator itr = NULL; - slurmdb_clus_res_rec_t *clus_rec = NULL; - licenses_t *match_lic = NULL; - licenses_t *new_license; - uint16_t rc = SLURM_SUCCESS; - char *cluster_name = NULL; - - cluster_name = slurm_get_cluster_name(); - itr = list_iterator_create(update_obj->objects); - while ((clus_rec = list_next(itr))) { - if (!strstr(clus_rec->cluster, cluster_name) || - clus_rec->res_ptr->type != SLURMDB_RESOURCE_LICENSE) - continue; - match_lic = list_find_first(clus_license_list, - _license_find_rec, clus_rec->res_ptr->name); - - if (match_lic == NULL) { - new_license = xmalloc(sizeof(licenses_t)); - new_license->name = xstrdup(clus_rec->res_ptr->name); - new_license->total = - ((clus_rec->res_ptr->count * - clus_rec->percent_allowed) / 100); - new_license->used = 0; - new_license->cluster = 1; - list_push(clus_license_list, new_license); - slurmdb_clus_res_rec_t *new_rec = - xmalloc(sizeof(slurmdb_clus_res_rec_t)); - slurmdb_init_clus_res_rec(new_rec, 0); - new_rec->res_ptr = xmalloc(sizeof( - slurmdb_ser_res_rec_t)); - slurmdb_init_ser_res_rec(new_rec->res_ptr, 0); - new_rec->res_ptr->description = - xstrdup(clus_rec->res_ptr->description); - new_rec->res_ptr->id = clus_rec->res_ptr->id; - new_rec->res_ptr->name = - xstrdup(clus_rec->res_ptr->name); - new_rec->res_ptr->count = clus_rec->res_ptr->count; - new_rec->res_ptr->type = clus_rec->res_ptr->type; - new_rec->res_ptr->manager = - xstrdup(clus_rec->res_ptr->manager); - new_rec->res_ptr->server = - xstrdup(clus_rec->res_ptr->server); - new_rec->cluster = xstrdup(clus_rec->cluster); - new_rec->percent_allowed = clus_rec->percent_allowed; - list_append(assoc_mgr_clus_res_list, new_rec); - } else { - error("cluster_resource_list already contains" - " this cluster license %s", - clus_rec->res_ptr->name); - rc = SLURM_ERROR; - break; - } - } - xfree(cluster_name); - list_iterator_destroy(itr); - return rc; -} - -/* update clus_license_list for a modified cluster license */ -static int _modify_clus_lic(List clus_license_list, - slurmdb_update_object_t *update_obj) -{ - ListIterator itr = NULL; - ListIterator itr2 = NULL; - slurmdb_clus_res_rec_t *clus_rec = NULL; - slurmdb_clus_res_rec_t *assoc_mgr_rec = NULL; - licenses_t *match_lic = NULL; - uint16_t rc = SLURM_SUCCESS; - char *cluster_name = NULL; - - cluster_name = slurm_get_cluster_name(); - itr = list_iterator_create(update_obj->objects); - itr2 = list_iterator_create(assoc_mgr_clus_res_list); - while ((clus_rec = list_next(itr))) { - if (!strstr(clus_rec->cluster, cluster_name) || - clus_rec->res_ptr->type != SLURMDB_RESOURCE_LICENSE) - continue; - match_lic = list_find_first(clus_license_list, - _license_find_rec, clus_rec->res_ptr->name); - if (match_lic) { - match_lic->total = - ((clus_rec->res_ptr->count * - clus_rec->percent_allowed) / 100); - while ((assoc_mgr_rec = list_next(itr2))) { - if (strstr(clus_rec->res_ptr->name, - assoc_mgr_rec->res_ptr->name)) { - assoc_mgr_rec->percent_allowed = - clus_rec->percent_allowed; - } - } - list_iterator_reset(itr2); - } else { - error("cluster_license_list doesn't contain %s", - clus_rec->res_ptr->name); - rc = SLURM_ERROR; - break; - } - } - xfree(cluster_name); - list_iterator_destroy(itr); - list_iterator_destroy(itr2); - return rc; -} - -/* update clus_license_list for a removed cluster license */ -static int _remove_clus_lic(List clus_license_list, - slurmdb_update_object_t *update_obj) -{ - ListIterator itr = NULL; - ListIterator itr2 = NULL; - ListIterator itr3 = NULL; - slurmdb_clus_res_rec_t *clus_rec = NULL; - slurmdb_clus_res_rec_t *assoc_mgr_rec = NULL; - licenses_t *license; - uint16_t temp; - uint16_t rc = SLURM_SUCCESS; - char *cluster_name = NULL; - - cluster_name = slurm_get_cluster_name(); - itr = list_iterator_create(update_obj->objects); - itr2 = list_iterator_create(clus_license_list); - itr3 = list_iterator_create(assoc_mgr_clus_res_list); - while ((clus_rec = list_next(itr))) { - if (!strstr(clus_rec->cluster, cluster_name) || - clus_rec->res_ptr->type != SLURMDB_RESOURCE_LICENSE) - continue; - while ((license = list_next(itr2))) { - if (strstr(clus_rec->res_ptr->name, license->name)) { - temp = list_delete_item(itr2); - if (!temp) { - error("clus_license_list removal" - "problem for %s", license->name); - rc = SLURM_ERROR; - break; - } - while ((assoc_mgr_rec = list_next(itr3))) { - if (strstr(clus_rec->res_ptr->name, - assoc_mgr_rec->res_ptr->name)) { - temp = list_delete_item(itr3); - if (!temp) { - error("assoc_mgr_clus_" - "res_list removal" - "problem for %s", - license->name); - rc = SLURM_ERROR; - break; - } - } - } - list_iterator_reset(itr3); - } - } - list_iterator_reset(itr2); - } - xfree(cluster_name); - list_iterator_destroy(itr); - list_iterator_destroy(itr2); - list_iterator_destroy(itr3); - return rc; -} - -/* create a list of license_t records from a list of clus_res_rec_t - * records - */ -static List _clus_license_init(List clus_rec_list) -{ - List clus_license_list = NULL; - ListIterator itr = NULL; - slurmdb_clus_res_rec_t *clus_rec = NULL; - licenses_t *license; - - if (!clus_rec_list) { - return NULL; - } - clus_license_list = list_create(license_free_rec); - itr = list_iterator_create(clus_rec_list ); - while ((clus_rec = list_next(itr))) { - license = xmalloc(sizeof(licenses_t)); - license->name = xstrdup(clus_rec->res_ptr->name); - license->total = - ((clus_rec->res_ptr->count * clus_rec->percent_allowed) / 100); - license->used = 0; - license->cluster = 1; - list_push(clus_license_list, license); - } - list_iterator_destroy(itr); - return clus_license_list; -} /* Initialize licenses on this system based upon slurm.conf * and information in the accounting database/ @@ -533,122 +249,250 @@ extern int license_init(char *licenses) if (!valid) fatal("Invalid configured licenses: %s", licenses); - if (assoc_mgr_clus_res_list) { - clus_license_list = _clus_license_init(assoc_mgr_clus_res_list); - license_list = merge_license_lists(license_list, - clus_license_list); - } - _licenses_print("init_license", license_list, 0); slurm_mutex_unlock(&license_mutex); - return SLURM_SUCCESS; } -/* Update the cluster license list for this system. - * Preserve all previously allocated licenses */ -static List _clus_license_list_update(slurmdb_update_object_t *update_obj) +/* Update licenses on this system based upon slurm.conf. +* Preserve all previously allocated licenses */ +extern int license_update(char *licenses) { - uint16_t type; - uint16_t rc = SLURM_SUCCESS; + ListIterator iter; + licenses_t *license_entry, *match; + List new_list; + bool valid; + + new_list = _build_license_list(licenses, &valid); + if (!valid) + fatal("Invalid configured licenses: %s", licenses); + + slurm_mutex_lock(&license_mutex); + if (!license_list) { /* no licenses before now */ + license_list = new_list; + slurm_mutex_unlock(&license_mutex); + return SLURM_SUCCESS; + } + + iter = list_iterator_create(license_list); + while ((license_entry = (licenses_t *) list_next(iter))) { + /* Always add the remote ones, since we handle those + else where. */ + if (license_entry->remote) { + list_remove(iter); + if (!new_list) + new_list = list_create(license_free_rec); + list_append(new_list, license_entry); + continue; + } + if (new_list) + match = list_find_first(new_list, _license_find_rec, + license_entry->name); + else + match = NULL; - if (!clus_license_list) { - if (assoc_mgr_clus_res_list) - clus_license_list = - _clus_license_init(assoc_mgr_clus_res_list); + if (!match) { + info("license %s removed with %u in use", + license_entry->name, license_entry->used); + } else { + match->used = license_entry->used; + if (match->used > match->total) { + info("license %s count decreased", + match->name); + } + } + } + list_iterator_destroy(iter); + + list_destroy(license_list); + license_list = new_list; + _licenses_print("update_license", license_list, 0); + slurm_mutex_unlock(&license_mutex); + return SLURM_SUCCESS; +} + +extern void license_add_remote(slurmdb_clus_res_rec_t *rec) +{ + licenses_t *license_entry; + ListIterator iter; + + xassert(rec); + xassert(rec->res_ptr); + xassert(rec->res_ptr->type == SLURMDB_RESOURCE_LICENSE); + + slurm_mutex_lock(&license_mutex); + if (!license_list) { + /* If last_license_update then init already ran and we + * don't have any licenses defined in the slurm.conf + * so make the license_list. + */ + xassert(last_license_update); + license_list = list_create(license_free_rec); } - type = update_obj->type; - switch ( type ) - { - case SLURMDB_MODIFY_SER_RES : - rc = _modify_ser_lic(clus_license_list, - assoc_mgr_clus_res_list, - update_obj); - break; - case SLURMDB_ADD_SER_RES : - case SLURMDB_REMOVE_SER_RES : - break; - case SLURMDB_ADD_CLUS_RES : - rc = _add_clus_lic(clus_license_list, update_obj); - break; - case SLURMDB_MODIFY_CLUS_RES : - rc = _modify_clus_lic(clus_license_list, update_obj); - break; - case SLURMDB_REMOVE_CLUS_RES : - rc = _remove_clus_lic(clus_license_list, update_obj); + + iter = list_iterator_create(license_list); + while ((license_entry = list_next(iter))) { + /* Should we look at all licenses not just + * remote ones? */ + if (!license_entry->remote) + continue; + if (!strcmp(license_entry->name, rec->res_ptr->name)) { + error("license_add_remote: license %s " + "already exists!", rec->res_ptr->name); break; + } } - if (rc != SLURM_SUCCESS) { - error("problem updating clus_license_list"); - return NULL; - } + list_iterator_destroy(iter); + + if (!license_entry) + _add_clus_rec_2_lic_list(rec, 0); - return clus_license_list; + slurm_mutex_unlock(&license_mutex); } -/* Update licenses on this system based upon slurm.conf. - * Preserve all previously allocated licenses */ -extern int license_update(char *licenses) +extern void license_update_remote(slurmdb_clus_res_rec_t *rec) { + licenses_t *license_entry; ListIterator iter; - licenses_t *license_entry, *match; - List new_list; - bool valid; - new_list = _build_license_list(licenses, &valid); - if (!valid) - fatal("Invalid configured licenses: %s", licenses); + xassert(rec); + xassert(rec->res_ptr); + xassert(rec->res_ptr->type == SLURMDB_RESOURCE_LICENSE); slurm_mutex_lock(&license_mutex); - if (!license_list) { /* no licenses before now */ - license_list = new_list; - slurm_mutex_unlock(&license_mutex); - return SLURM_SUCCESS; + if (!license_list) { + /* If last_license_update then init already ran and we + * don't have any licenses defined in the slurm.conf + * so make the license_list. + */ + xassert(last_license_update); + license_list = list_create(license_free_rec); } iter = list_iterator_create(license_list); - while ((license_entry = (licenses_t *) list_next(iter))) { - match = list_find_first(new_list, _license_find_rec, - license_entry->name); - if (!match) { - info("license %s removed with %u in use", - license_entry->name, license_entry->used); - } else { - match->used = license_entry->used; - match->cluster = 0; - if (match->used > match->total) { + while ((license_entry = list_next(iter))) { + /* Should we look at all licenses not just + * remote ones? */ + if (!license_entry->remote) + continue; + if (!strcmp(license_entry->name, rec->res_ptr->name)) { + license_entry->total = + ((rec->res_ptr->count * + rec->percent_allowed) / 100); + if (license_entry->used > + license_entry->total) { info("license %s count decreased", - match->name); + license_entry->name); } + last_license_update = time(NULL); + break; } } list_iterator_destroy(iter); + if (!license_entry) { + debug("license_update_remote: License '%s' not found, adding", + rec->res_ptr->name); + _add_clus_rec_2_lic_list(rec, 0); + } + slurm_mutex_unlock(&license_mutex); +} + +extern void license_remove_remote(slurmdb_clus_res_rec_t *rec) +{ + licenses_t *license_entry; + ListIterator iter; + + xassert(rec); + xassert(rec->res_ptr); + xassert(rec->res_ptr->type == SLURMDB_RESOURCE_LICENSE); - list_destroy(license_list); - license_list = new_list; - _licenses_print("update_license", license_list, 0); + slurm_mutex_lock(&license_mutex); + if (!license_list) { + xassert(last_license_update); + license_list = list_create(license_free_rec); + } + + iter = list_iterator_create(license_list); + while ((license_entry = list_next(iter))) { + /* Should we look at all licenses not just + * remote ones? */ + if (!license_entry->remote) + continue; + if (!strcmp(license_entry->name, rec->res_ptr->name)) { + info("license_remove_remote: license %s " + "removed with %u in use", + license_entry->name, license_entry->used); + list_delete_item(iter); + last_license_update = time(NULL); + break; + } + } + list_iterator_destroy(iter); + if (!license_entry) + error("license_remote_remote: License '%s' not found", + rec->res_ptr->name); slurm_mutex_unlock(&license_mutex); - return SLURM_SUCCESS; } -/* Update cluster licenses on this system based upon accounting database. - * Preserve all previously allocated licenses */ -extern int cluster_license_update(slurmdb_update_object_t *update_obj) +extern void license_sync_remote(List clus_res_list) { - List clus_license_list; + slurmdb_clus_res_rec_t *rec = NULL; + licenses_t *license_entry; + ListIterator iter; slurm_mutex_lock(&license_mutex); - clus_license_list = _clus_license_list_update(update_obj); + if (clus_res_list && !license_list) { + xassert(last_license_update); + license_list = list_create(license_free_rec); + } - if (!license_list) { /* no licenses before now */ - license_list = clus_license_list; - } else { - if (clus_license_list) - license_list = - merge_license_lists(license_list, clus_license_list); + iter = list_iterator_create(license_list); + if (clus_res_list) { + ListIterator iter2 = list_iterator_create(clus_res_list); + while ((rec = list_next(iter2))) { + if (rec->res_ptr->type != SLURMDB_RESOURCE_LICENSE) + continue; + while ((license_entry = list_next(iter))) { + if (!license_entry->remote) + continue; + if (!strcmp(license_entry->name, + rec->res_ptr->name)) { + license_entry->remote = 2; + license_entry->total = + ((rec->res_ptr->count * + rec->percent_allowed) / 100); + if (license_entry->used > + license_entry->total) { + info("license %s count " + "decreased", + license_entry->name); + } + last_license_update = time(NULL); + break; + } + } + if (!license_entry) + _add_clus_rec_2_lic_list(rec, 1); + list_iterator_reset(iter); + } + list_iterator_destroy(iter2); + } + + while ((license_entry = list_next(iter))) { + if (!license_entry->remote) + continue; + else if (license_entry->remote == 1) { + info("license_remove_remote: license %s " + "removed with %u in use", + license_entry->name, license_entry->used); + list_delete_item(iter); + last_license_update = time(NULL); + } else if (license_entry->remote == 2) + license_entry->remote = 1; } + list_iterator_destroy(iter); + slurm_mutex_unlock(&license_mutex); - return SLURM_SUCCESS; } /* Free memory associated with licenses on this system */ @@ -937,9 +781,7 @@ get_all_license_info(char **buffer_ptr, pack_time(now, buffer); slurm_mutex_lock(&license_mutex); - if (license_list) { - iter = list_iterator_create(license_list); while ((lic_entry = list_next(iter))) { /* Now encode the license data structure. @@ -971,7 +813,7 @@ get_all_license_info(char **buffer_ptr, * char * name; * uint32_t total; * uint32_t used; - * uint32_t cluster; + * uint8_t remote; * */ static void @@ -981,7 +823,7 @@ _pack_license(struct licenses *lic, Buf buffer, uint16_t protocol_version) packstr(lic->name, buffer); pack32(lic->total, buffer); pack32(lic->used, buffer); - pack32(lic->cluster, buffer); + pack8(lic->remote, buffer); } else { error("\ %s: protocol_version %hu not supported", __func__, protocol_version); diff --git a/src/slurmctld/licenses.h b/src/slurmctld/licenses.h index e7c867fcc59fbf625e28ee88bd485e43e05a49ac..5f2c03861c8c744871777447ae076b0178492d66 100644 --- a/src/slurmctld/licenses.h +++ b/src/slurmctld/licenses.h @@ -46,17 +46,13 @@ typedef struct licenses { char * name; /* name associated with a license */ uint32_t total; /* total license configued */ uint32_t used; /* used licenses */ - uint32_t cluster; /* non-zero if cluster_license */ + uint8_t remote; /* non-zero if remote (from database) */ } licenses_t; extern List license_list; extern List clus_license_list; extern time_t last_license_update; -/* Update cluster licenses on this system based upon database information. - * Preserve all previously allocated licenses */ -extern int cluster_license_update(slurmdb_update_object_t *update_obj); - /* Get string of used license information. Caller must xfree return value */ extern char *get_licenses_used(void); @@ -67,9 +63,10 @@ extern int license_init(char *licenses); * Preserve all previously allocated licenses */ extern int license_update(char *licenses); -/* Update cluster licenses on this system based upon accounting database. - * Preserve all previously allocated licenses */ -extern int cluster_license_update(slurmdb_update_object_t *update_obj); +extern void license_add_remote(slurmdb_clus_res_rec_t *rec); +extern void license_update_remote(slurmdb_clus_res_rec_t *rec); +extern void license_remove_remote(slurmdb_clus_res_rec_t *rec); +extern void license_sync_remote(List clus_res_list); /* Free memory associated with licenses on this system */ extern void license_free(void); diff --git a/testsuite/expect/test21.31 b/testsuite/expect/test21.31 old mode 100644 new mode 100755