blob: 0f46389822776e9ebabd50557116d9b75f2555fc [file] [log] [blame]
/*****************************************************************************\
* step_ctx.c - step_ctx task functions for use by AIX/POE
*****************************************************************************
* Copyright (C) 2004-2007 The Regents of the University of California.
* Copyright (C) 2008-2010 Lawrence Livermore National Security.
* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
* Written by Morris Jette <jette1@llnl.gov>.
* CODE-OCEC-09-009. All rights reserved.
*
* This file is part of Slurm, a resource management program.
* For details, see <https://slurm.schedmd.com/>.
* Please also read the included file: DISCLAIMER.
*
* Slurm is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* In addition, as a special exception, the copyright holders give permission
* to link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two. You must obey the GNU
* General Public License in all respects for all of the code used other than
* OpenSSL. If you modify file(s) with this exception, you may extend this
* exception to your version of the file(s), but you are not obligated to do
* so. If you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files in
* the program, then also delete it here.
*
* Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with Slurm; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\*****************************************************************************/
#include <errno.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "slurm/slurm.h"
#include "src/common/bitstring.h"
#include "src/common/hostlist.h"
#include "src/common/net.h"
#include "src/common/read_config.h"
#include "src/interfaces/cred.h"
#include "src/common/slurm_protocol_api.h"
#include "src/common/slurm_protocol_defs.h"
#include "src/interfaces/switch.h"
#include "src/common/timers.h"
#include "src/common/xmalloc.h"
#include "src/common/xsignal.h"
#include "src/common/xstring.h"
#include "step_ctx.h"
#include "launch.h"
int step_signals[] = {
SIGINT, SIGQUIT, SIGCONT, SIGTERM, SIGHUP,
SIGALRM, SIGUSR1, SIGUSR2, SIGPIPE, 0 };
static int destroy_step = 0;
static void _signal_while_allocating(int signo)
{
debug("Got signal %d", signo);
if (signo == SIGCONT)
return;
destroy_step = signo;
}
static void _job_fake_cred(struct slurm_step_ctx_struct *ctx)
{
uint32_t node_cnt = ctx->step_resp->step_layout->node_cnt;
slurm_cred_arg_t *arg = xmalloc(sizeof(*arg));
memcpy(&arg->step_id, &ctx->step_req->step_id, sizeof(arg->step_id));
arg->uid = getuid();
arg->job_nhosts = node_cnt;
arg->job_hostlist = ctx->step_resp->step_layout->node_list;
arg->job_mem_alloc = xmalloc(sizeof(uint64_t));
arg->job_mem_alloc[0] = 0;
arg->job_mem_alloc_rep_count = xmalloc(sizeof(uint64_t));
arg->job_mem_alloc_rep_count[0] = node_cnt;
arg->job_mem_alloc_size = 1;
arg->step_hostlist = ctx->step_req->node_list;
arg->step_mem_alloc = xmalloc(sizeof(uint64_t));
arg->step_mem_alloc[0] = 0;
arg->step_mem_alloc_rep_count = xmalloc(sizeof(uint64_t));
arg->step_mem_alloc_rep_count[0] = node_cnt;
arg->step_mem_alloc_size = 1;
arg->job_core_bitmap = bit_alloc(node_cnt);
bit_set_all(arg->job_core_bitmap);
arg->step_core_bitmap = bit_alloc(node_cnt);
bit_set_all(arg->step_core_bitmap);
arg->cores_per_socket = xmalloc(sizeof(uint16_t));
arg->cores_per_socket[0] = 1;
arg->sockets_per_node = xmalloc(sizeof(uint16_t));
arg->sockets_per_node[0] = 1;
arg->sock_core_rep_count = xmalloc(sizeof(uint32_t));
arg->sock_core_rep_count[0] = node_cnt;
ctx->step_resp->cred = slurm_cred_faker(arg);
/* Don't free, this memory will be free'd later */
arg->job_hostlist = NULL;
arg->step_hostlist = NULL;
slurm_cred_free_args(arg);
}
/*
* step_ctx_create - Create a job step and its context.
* IN step_params - job step parameters
* IN timeout - in milliseconds
* OUT timed_out - indicate if poll timed-out
* RET the step context or NULL on failure with slurm errno set
* NOTE: Free allocated memory using slurm_step_ctx_destroy.
*/
extern slurm_step_ctx_t *step_ctx_create_timeout(
job_step_create_request_msg_t *step_req, int timeout, bool *timed_out)
{
struct slurm_step_ctx_struct *ctx = NULL;
job_step_create_response_msg_t *step_resp = NULL;
int i, rc, time_left;
int sock = -1;
uint16_t port = 0;
int errnum = 0;
int cc;
uint16_t *ports;
struct pollfd fds;
long elapsed_time;
DEF_TIMERS;
xassert(step_req);
/*
* We will handle the messages in the step_launch.c message handler,
* but we need to open the socket right now so we can tell the
* controller which port to use.
*/
if ((ports = slurm_get_srun_port_range()))
cc = net_stream_listen_ports(&sock, &port, ports, false);
else
cc = net_stream_listen(&sock, &port);
if (cc < 0) {
error("unable to initialize step request socket: %m");
return NULL;
}
step_req->port = port;
rc = slurm_job_step_create(step_req, &step_resp);
if ((rc < 0) && launch_common_step_retry_errno(errno)) {
START_TIMER;
errnum = errno;
fds.fd = sock;
fds.events = POLLIN;
xsignal_unblock(step_signals);
for (i = 0; step_signals[i]; i++)
xsignal(step_signals[i], _signal_while_allocating);
while (1) {
END_TIMER;
elapsed_time = DELTA_TIMER / 1000;
if (elapsed_time >= timeout)
break;
time_left = timeout - elapsed_time;
i = poll(&fds, 1, time_left);
if (i == 0)
*timed_out = true;
if ((i >= 0) || destroy_step)
break;
if ((errno == EINTR) || (errno == EAGAIN))
continue;
break;
}
xsignal_block(step_signals);
if (destroy_step) {
info("Cancelled pending job step with signal %d",
destroy_step);
errnum = ESLURM_ALREADY_DONE;
}
close(sock);
errno = errnum;
} else if ((rc < 0) || (step_resp == NULL)) {
close(sock);
} else {
ctx = xmalloc(sizeof(struct slurm_step_ctx_struct));
ctx->launch_state = NULL;
ctx->magic = STEP_CTX_MAGIC;
ctx->job_id = step_req->step_id.job_id;
ctx->step_req = step_req;
/*
* Grab the step id here if we don't already have it, we will
* need to to send to the slurmd.
*/
if (step_req->step_id.step_id == NO_VAL)
step_req->step_id.step_id = step_resp->job_step_id;
if (step_req->array_task_id != NO_VAL) {
step_req->step_id.job_id = step_resp->job_id;
ctx->job_id = step_resp->job_id;
}
ctx->step_resp = step_resp;
ctx->launch_state = step_launch_state_create(ctx);
ctx->launch_state->slurmctld_socket_fd = sock;
}
return (slurm_step_ctx_t *) ctx;
}
/*
* step_ctx_create_no_alloc - Create a job step and its context without
* getting an allocation.
* IN step_params - job step parameters
* IN step_id - since we are faking it give me the id to use
* RET the step context or NULL on failure with slurm errno set
* NOTE: Free allocated memory using slurm_step_ctx_destroy.
*/
extern slurm_step_ctx_t *step_ctx_create_no_alloc(
job_step_create_request_msg_t *step_req, uint32_t step_id)
{
struct slurm_step_ctx_struct *ctx = NULL;
job_step_create_response_msg_t *step_resp = NULL;
int sock = -1;
uint16_t port = 0;
uint16_t *ports;
int rc;
xassert(step_req);
/* We will handle the messages in the step_launch.c message handler,
* but we need to open the socket right now so we can tell the
* controller which port to use.
*/
ports = slurm_get_srun_port_range();
if (ports)
rc = net_stream_listen_ports(&sock, &port, ports, false);
else
rc = net_stream_listen(&sock, &port);
if (rc < 0) {
error("unable to initialize step context socket: %m");
return NULL;
}
step_req->port = port;
/* Then make up a response with only certain things filled in */
step_resp = (job_step_create_response_msg_t *)
xmalloc(sizeof(job_step_create_response_msg_t));
step_resp->step_layout = fake_slurm_step_layout_create(
step_req->node_list,
NULL, NULL,
step_req->min_nodes,
step_req->num_tasks,
0);
step_resp->job_step_id = step_id;
ctx = xmalloc(sizeof(struct slurm_step_ctx_struct));
ctx->launch_state = NULL;
ctx->magic = STEP_CTX_MAGIC;
ctx->job_id = step_req->step_id.job_id;
ctx->step_req = step_req;
/*
* Grab the step id here if we don't already have it, we will
* need to to send to the slurmd.
*/
if (step_req->step_id.step_id == NO_VAL)
step_req->step_id.step_id = step_resp->job_step_id;
ctx->step_resp = step_resp;
ctx->launch_state = step_launch_state_create(ctx);
ctx->launch_state->slurmctld_socket_fd = sock;
_job_fake_cred(ctx);
return (slurm_step_ctx_t *)ctx;
}
/*
* step_ctx_destroy - free allocated memory for a job step context.
* IN ctx - job step context generated by slurm_step_ctx_create
* RET SLURM_SUCCESS or SLURM_ERROR (with slurm_errno set)
*/
extern int step_ctx_destroy(slurm_step_ctx_t *ctx)
{
if ((ctx == NULL) || (ctx->magic != STEP_CTX_MAGIC)) {
errno = EINVAL;
return SLURM_ERROR;
}
slurm_free_job_step_create_request_msg(ctx->step_req);
slurm_free_job_step_create_response_msg(ctx->step_resp);
step_launch_state_destroy(ctx->launch_state);
xfree(ctx);
return SLURM_SUCCESS;
}