def get_session_id_from_request(request): """ Utility function that returns the session ID from a given HTTP request :return: a UUID session identifier """ log.debug(1, 'Getting cookie from request') return request.QUERY_PARAMS[consts.REQUEST_PARAMETER_SESSIONID]
def test_duplicate_settings(self): log.debug(1, 'test_duplicate_settings') manager = RenderingResourceSettingsManager() params = dict() params['id'] = 'rtneuron' params['command_line'] = 'rtneuron-app.py' params['environment_variables'] = \ 'EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512' params['modules'] = 'BBP/viz/latest' params['process_rest_parameters_format'] = '--rest {$rest_hostname}:${rest_port}' params['scheduler_rest_parameters_format'] = '--rest $SLURMD_NODENAME:${rest_port}' params['project'] = 'project' params['queue'] = 'test' params['exclusive'] = False params['nb_nodes'] = 1 params['nb_cpus'] = 1 params['nb_gpus'] = 1 params['graceful_exit'] = True params['wait_until_running'] = True params['name'] = 'name' params['description'] = 'description' status = manager.create(params) nt.assert_true(status[0] == 201) # Duplicate status = manager.create(params) nt.assert_true(status[0] == 409) # Delete Settings status = manager.delete(params['id']) nt.assert_true(status[0] == 200)
def test_delete_invalid_session(self): log.debug(1, 'test_delete_invalid_session') session_id = SessionManager.get_session_id() # Delete session sm = SessionManager() status = sm.delete_session(session_id) nt.assert_true(status[0] == 404)
def create_session(cls, session_id, owner, renderer_id): """ Creates a user session :param session_id: Id for the new session :param owner: Session owner :param renderer_id: Id of the renderer associated to the session :rtype A tuple containing the status and the description of the potential error """ sgs = SystemGlobalSettings.objects.get() if sgs.session_creation: try: session = Session( id=session_id, owner=owner, renderer_id=renderer_id, created=datetime.datetime.utcnow(), valid_until=datetime.datetime.now() + datetime.timedelta(seconds=sgs.session_keep_alive_timeout)) with transaction.atomic(): session.save(force_insert=True) msg = 'Session successfully created' log.debug(1, msg) response = json.dumps({'contents': msg}) return [http_status.HTTP_201_CREATED, response] except IntegrityError as e: log.error(e) response = json.dumps({'contents': str(e)}) return [http_status.HTTP_409_CONFLICT, response] else: msg = 'Session creation is currently suspended' log.error(msg) response = json.dumps({'contents': str(msg)}) return [http_status.HTTP_403_FORBIDDEN, response]
def test_duplicate_settings(self): log.debug(1, 'test_duplicate_settings') manager = RenderingResourceSettingsManager() params = dict() params['id'] = 'rtneuron' params['command_line'] = 'rtneuron-app.py' params['environment_variables'] = \ 'EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512' params['modules'] = 'BBP/viz/latest' params['process_rest_parameters_format'] = '--rest {$rest_hostname}:${rest_port}' params['scheduler_rest_parameters_format'] = '--rest $SLURMD_NODENAME:${rest_port}' params['project'] = 'project' params['queue'] = 'test' params['exclusive'] = False params['nb_nodes'] = 1 params['nb_cpus'] = 1 params['nb_gpus'] = 1 params['memory'] = 0 params['graceful_exit'] = True params['wait_until_running'] = True params['name'] = 'name' params['description'] = 'description' status = manager.create(params) nt.assert_true(status[0] == 201) # Duplicate status = manager.create(params) nt.assert_true(status[0] == 409) # Delete Settings status = manager.delete(params['id']) nt.assert_true(status[0] == 200)
def test_delete_invalid_settings(self): log.debug(1, 'test_delete_invalid_settings') manager = RenderingResourceSettingsManager() params = dict() params['id'] = '@%$#$' # Delete Settings status = manager.delete(params) nt.assert_true(status[0] == 404)
def setUp(self): log.debug(1, 'setUp') sm = SessionManager() # Clear sessions status = sm.clear_sessions() nt.assert_true(status[0] == 200) # List sessions status = sm.resume_sessions() nt.assert_true(status[0] == 200)
def test_create_session(self): log.debug(1, 'test_create_session') session_id = SessionManager.get_session_id() # Create session sm = SessionManager() status = sm.create_session(session_id, DEFAULT_USER, DEFAULT_RENDERER) nt.assert_true(status[0] == 201) # Delete new session status = sm.delete_session(session_id) nt.assert_true(status[0] == 200)
def get_session_id_from_request(request): """ Utility function that returns the session ID from a given HTTP request :return: a UUID session identifier """ log.debug(1, 'Getting cookie from request') try: session_id = request.COOKIES[consts.COOKIE_ID] except KeyError as e: session_id = SessionManager.get_session_id() log.info(1, 'Cookie ' + str(e) + ' is missing. New session ID is ' + str(session_id)) return session_id
def resume_sessions(cls): """ Resumes the creation of new session. """ sgs = SystemGlobalSettings.objects.get(id=0) if sgs.session_creation: msg = 'Session creation already resumed' else: sgs.session_creation = True sgs.save() msg = 'Creation of new session now resumed' log.debug(1, msg) return [http_status.HTTP_200_OK, msg]
def suspend_sessions(cls): """ Suspends the creation of new session. This administration feature is here to prevent overloading of the system """ sgs = SystemGlobalSettings.objects.get(id=0) if not sgs.session_creation: msg = 'Session creation already suspended' else: sgs.session_creation = False sgs.save() msg = 'Creation of new session now suspended' log.debug(1, msg) return [http_status.HTTP_200_OK, msg]
def start(session_info, params, environment): """ Gently starts a given process, waits for 2 seconds and checks for its appearance :param session_info: Session information containing the PID of the process :return: A Json response containing on ok status or a description of the error """ try: settings = manager.RenderingResourceSettingsManager.get_by_id( session_info.renderer_id.lower()) default_parameters = manager.RenderingResourceSettingsManager.format_rest_parameters( str(settings.process_rest_parameters_format), str(session_info.http_host), str(session_info.http_port), 'rest' + str(settings.id + session_info.id)) command_line = [ str(settings.command_line) ] + default_parameters.split() try: command_line += str(params).split() except KeyError: log.debug(1, 'No parameters specified') except TypeError: log.debug(1, 'No parameters specified') environment_variables = settings.environment_variables.split() + environment.split(',') process_env = os.environ.copy() for environment_variable in environment_variables: if environment_variable != '': variable = environment_variable.split('=') process_env[variable[0]] = variable[1] log.info(1, 'Launching ' + settings.id + ' with ' + str(command_line)) process = subprocess.Popen( command_line, env=process_env, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE) session_info.process_pid = process.pid session_info.status = SESSION_STATUS_STARTING response = json.dumps( {'message': 'Process started', 'processId': str(session_info.process_pid)}) return [200, response] except RenderingResourceSettings.DoesNotExist as e: log.error(str(e)) response = json.dumps({'contents': str(e)}) return [404, response]
def keep_alive_session(cls, session_id): """ Updated the specified session with a new expiration timestamp :param session_id: Id of the session to update """ log.debug(1, 'Session ' + str(session_id) + ' is being updated') try: sgs = SystemGlobalSettings.objects.get(id=0) session = Session.objects.get(id=session_id) session.valid_until = datetime.datetime.now() + \ datetime.timedelta(seconds=sgs.session_keep_alive_timeout) session.save() msg = 'Session ' + str(session_id) + ' successfully updated' return [http_status.HTTP_200_OK, msg] except Session.DoesNotExist as e: log.error(str(e)) return [http_status.HTTP_404_NOT_FOUND, str(e)]
def test_session_status(self): log.debug(1, 'test_session_status') session_id = SessionManager.get_session_id() sm = SessionManager() # Create session status = sm.create_session(session_id, DEFAULT_USER, DEFAULT_RENDERER) nt.assert_true(status[0] == 201) # Check session status (must be STOPPED) sm = SessionManager() status = sm.query_status(session_id) js = json.loads(status[1]) nt.assert_true(status[0] == 200) nt.assert_true(js['code'] == 0) # Delete session sm = SessionManager() status = sm.delete_session(session_id) nt.assert_true(status[0] == 200)
def __session_status(cls, session): """ Forwards the HTTP request to the rendering resource held by the given session :param : session: Session holding the rendering resource :param : command: Command passed to the rendering resource :param : request: HTTP request :rtype : An HTTP response containing the status and description of the command """ # check if the hostname of the rendering resource is currently available status = cls.__verify_hostname(session) if status[0] != 200: return status # query the status of the current session status = session_manager.SessionManager.query_status(session.id) if status[0] == 200: return status else: msg = 'Rendering resource is not yet available: ' + status[1] log.debug(1, msg) return status
def test_list_sessions(self): log.debug(1, 'test_list_sessions') session_id = SessionManager.get_session_id() sm = SessionManager() # Create session status = sm.create_session(session_id, DEFAULT_USER, DEFAULT_RENDERER) nt.assert_true(status[0] == 201) # List sessions sm = SessionManager() status = sm.list_sessions(SessionDetailsSerializer) nt.assert_true(status[0] == 200) # Decode JSON response decoded = json.loads(status[1].content) nt.assert_true(decoded[0]['owner'] == DEFAULT_USER) nt.assert_true(decoded[0]['renderer_id'] == DEFAULT_RENDERER) # Delete session sm = SessionManager() status = sm.delete_session(session_id) nt.assert_true(status[0] == 200)
def test_suspend_resume_sessions(self): log.debug(1, 'test_suspend_resume_sessions') session_id = SessionManager.get_session_id() sm = SessionManager() # Suspend sessions status = sm.suspend_sessions() nt.assert_true(status[0] == 200) # Create session status = sm.create_session(session_id, DEFAULT_USER, DEFAULT_RENDERER) nt.assert_true(status[0] == 403) # List sessions sm = SessionManager() status = sm.resume_sessions() nt.assert_true(status[0] == 200) # Create session status = sm.create_session(session_id, DEFAULT_USER, DEFAULT_RENDERER) nt.assert_true(status[0] == 201) # Delete session sm = SessionManager() status = sm.delete_session(session_id) nt.assert_true(status[0] == 200)
def __open_process(cls, session, request): """ Starts a local rendering resource process :param : session: Session holding the rendering resource :param : request: HTTP request with a body containing a JSON representation of the process parameters :rtype : An HTTP response containing the status and description of the command """ parameters = '' try: parameters = request.DATA['params'] except KeyError: log.debug(1, 'No parameters specified') environment = '' try: environment = request.DATA['environment'] except KeyError: log.debug(1, 'No environment specified') log.debug(1, 'Executing command <Open> parameters=' + str(parameters) + ' environment=' + str(environment)) if session.process_pid == -1: session.http_host = consts.DEFAULT_RENDERER_HOST session.http_port = consts.DEFAULT_RENDERER_HTTP_PORT + random.randint(0, 1000) pm = process_manager.ProcessManager status = pm.start(session, parameters, environment) session.save() return HttpResponse(status=status[0], content=status[1]) else: msg = 'process is already started' log.error(msg) response = json.dumps({'contents': str(msg)}) return HttpResponse(status=401, content=response)
def test_format_rest_parameters(self): log.debug(1, 'test_format_rest_parameters') manager = RenderingResourceSettingsManager() # test 1 value = manager.format_rest_parameters( '--rest ${rest_hostname}:${rest_port}', 'localhost', 3000, 'schema') nt.assert_true(value == '--rest localhost:3000') # test 2 value = manager.format_rest_parameters( '--rest ${rest_hostname}:${rest_port} --rest-schema ${rest_schema}', 'localhost', 3000, 'schema') nt.assert_true(value == '--rest localhost:3000 --rest-schema schema') # test 3 value = manager.format_rest_parameters( '--rest ${rest_hostname}:${rest_port} --rest-schema ${rest_schema}', 'localhost', 3000, 'schema') nt.assert_true(value == '--rest localhost:3000 --rest-schema schema') # test 4 value = manager.format_rest_parameters( '--rest ${rest_hostname}:${rest_port} --rest-schema ${rest_schema}', 'localhost', '3000', 'schema') nt.assert_true(value == '--rest localhost:3000 --rest-schema schema') # test 5 value = manager.format_rest_parameters( '--rest $SLURMD_NODENAME:${rest_port}', 'localhost', 3000, 'schema') nt.assert_true(value == '--rest $SLURMD_NODENAME:3000') # test 6 value = manager.format_rest_parameters( '--rest ${rest_hostname}:${rest_port}:${rest_schema}', 'localhost', 3000, 'schema') nt.assert_true(value == '--rest localhost:3000:schema')
def execute(cls, request, command): """ Executes a command on the rendering resource :param : request: The REST request :param : command: Command to be executed on the rendering resource :rtype : A Json response containing on ok status or a description of the error """ # pylint: disable=R0912 try: session_id = session_manager.SessionManager( ).get_session_id_from_request(request) log.debug( 1, 'Processing command <' + command + '> for session ' + str(session_id)) session = Session.objects.get(id=session_id) response = None if command == 'schedule': response = cls.__schedule_job(session, request) elif command == 'open': response = cls.__open_process(session, request) elif command == 'status': status = cls.__session_status(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'log': status = cls.__rendering_resource_out_log(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'err': status = cls.__rendering_resource_err_log(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'job': status = cls.__job_information(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'imagefeed': status = cls.__image_feed(session_id) response = HttpResponse(status=status[0], content=status[1]) else: url = request.get_full_path() prefix = settings.BASE_URL_PREFIX + '/session/' cmd = url[url.find(prefix) + len(prefix) + 1:len(url)] response = cls.__forward_request(session, cmd, request) return response except (KeyError, TypeError) as e: log.debug(1, str(traceback.format_exc(e))) response = json.dumps({'contents': 'Cookie is missing'}) return HttpResponse(status=404, content=response) except Session.DoesNotExist as e: log.debug(1, str(traceback.format_exc(e))) response = json.dumps({'contents': 'Session does not exist'}) return HttpResponse(status=404, content=response) except Exception as e: msg = traceback.format_exc(e) log.error(str(msg)) response = json.dumps({'contents': str(msg)}) return HttpResponse(status=500, content=response)
def execute(cls, request, command): """ Executes a command on the rendering resource :param : request: The REST request :param : command: Command to be executed on the rendering resource :rtype : A Json response containing on ok status or a description of the error """ # pylint: disable=R0912 try: session_id = session_manager.SessionManager().get_session_id_from_request(request) log.debug(1, 'Processing command <' + command + '> for session ' + str(session_id)) session = Session.objects.get(id=session_id) response = None if command == 'schedule': response = cls.__schedule_job(session, request) elif command == 'open': response = cls.__open_process(session, request) elif command == 'status': status = cls.__session_status(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'log': status = cls.__rendering_resource_out_log(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'err': status = cls.__rendering_resource_err_log(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'job': status = cls.__job_information(session) response = HttpResponse(status=status[0], content=status[1]) elif command == 'imagefeed': status = cls.__image_feed(session_id) response = HttpResponse(status=status[0], content=status[1]) else: url = request.get_full_path() prefix = settings.BASE_URL_PREFIX + '/session/' cmd = url[url.find(prefix) + len(prefix) + 1: len(url)] response = cls.__forward_request(session, cmd, request) return response except KeyError as e: log.debug(1, str(traceback.format_exc(e))) response = json.dumps({'contents': 'Cookie ' + str(e) + ' is missing'}) return HttpResponse(status=404, content=response) except Session.DoesNotExist as e: log.debug(1, str(traceback.format_exc(e))) response = json.dumps({'contents': 'Session does not exist'}) return HttpResponse(status=404, content=response) except Exception as e: msg = traceback.format_exc(e) log.error(str(msg)) response = json.dumps({'contents': str(msg)}) return HttpResponse(status=500, content=response)
def __open_process(cls, session, request): """ Starts a local rendering resource process :param : session: Session holding the rendering resource :param : request: HTTP request with a body containing a JSON representation of the process parameters :rtype : An HTTP response containing the status and description of the command """ parameters = '' try: parameters = request.DATA['params'] except KeyError: log.debug(1, 'No parameters specified') environment = '' try: environment = request.DATA['environment'] except KeyError: log.debug(1, 'No environment specified') log.debug( 1, 'Executing command <Open> parameters=' + str(parameters) + ' environment=' + str(environment)) if session.process_pid == -1: session.http_host = consts.DEFAULT_RENDERER_HOST session.http_port = consts.DEFAULT_RENDERER_HTTP_PORT + random.randint( 0, 1000) pm = process_manager.ProcessManager status = pm.start(session, parameters, environment) session.save() return HttpResponse(status=status[0], content=status[1]) else: msg = 'process is already started' log.error(msg) response = json.dumps({'contents': str(msg)}) return HttpResponse(status=401, content=response)
def tearDown(self): log.debug(1, 'tearDown') # Clear session manager = RenderingResourceSettingsManager() status = manager.clear() nt.assert_true(status[0] == 200)
def setUp(self): log.debug(1, 'setUp') manager = RenderingResourceSettingsManager() # Clear session status = manager.clear() nt.assert_true(status[0] == 200)
def test_list_settings(self): log.debug(1, 'test_list_settings') manager = RenderingResourceSettingsManager() params = dict() params['id'] = 'rtneuron' params['command_line'] = 'rtneuron-app.py' params['environment_variables'] = \ 'EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512' params['modules'] = 'BBP/viz/latest' params['process_rest_parameters_format'] = '--rest {$rest_hostname}:${rest_port}' params['scheduler_rest_parameters_format'] = '--rest $SLURMD_NODENAME:${rest_port}' params['project'] = 'project' params['queue'] = 'test' params['exclusive'] = False params['nb_nodes'] = 1 params['nb_cpus'] = 1 params['nb_gpus'] = 1 params['memory'] = 0 params['graceful_exit'] = True params['wait_until_running'] = True params['name'] = 'name' params['description'] = 'description' status = manager.create(params) nt.assert_true(status[0] == 201) params['id'] = 'livre' params['command_line'] = 'livre' params['environment_variables'] = \ 'EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512' params['modules'] = 'BBP/viz/2015.R3' params['process_rest_parameters_format'] = \ '--rest {$rest_hostname}:${rest_port}:${rest_schema}' params['scheduler_rest_parameters_format'] = \ '--rest $SLURMD_NODENAME:${rest_port}:${rest_schema}' params['project'] = 'project' params['queue'] = 'test' params['exclusive'] = False params['nb_nodes'] = 1 params['nb_cpus'] = 1 params['nb_gpus'] = 1 params['memory'] = 0 params['graceful_exit'] = True params['wait_until_running'] = True params['name'] = 'name' params['description'] = 'description' status = manager.create(params) nt.assert_true(status[0] == 201) status = manager.list(RenderingResourceSettingsSerializer) nt.assert_true(status[0] == 200) value = status[1] reference = '[' \ '{"id": "livre", ' \ '"command_line": "livre", ' \ '"environment_variables": ' \ '"EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512", ' \ '"modules": ' \ '"BBP/viz/2015.R3", ' \ '"process_rest_parameters_format": ' \ '"--rest {$rest_hostname}:${rest_port}:${rest_schema}", ' \ '"scheduler_rest_parameters_format": ' \ '"--rest $SLURMD_NODENAME:${rest_port}:${rest_schema}", ' \ '"project": "project", ' \ '"queue": "test", ' \ '"exclusive": false, ' \ '"nb_nodes": 1, ' \ '"nb_cpus": 1, ' \ '"nb_gpus": 1, ' \ '"memory": 0, ' \ '"graceful_exit": true, ' \ '"wait_until_running": true, ' \ '"name": "name", ' \ '"description": "description"}, ' \ '{"id": "rtneuron", ' \ '"command_line": "rtneuron-app.py", ' \ '"environment_variables": ' \ '"EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512", ' \ '"modules": "BBP/viz/latest", ' \ '"process_rest_parameters_format": ' \ '"--rest {$rest_hostname}:${rest_port}", ' \ '"scheduler_rest_parameters_format": ' \ '"--rest $SLURMD_NODENAME:${rest_port}", ' \ '"project": "project", ' \ '"queue": "test", ' \ '"exclusive": false, ' \ '"nb_nodes": 1, ' \ '"nb_cpus": 1, ' \ '"nb_gpus": 1, ' \ '"memory": 0, ' \ '"graceful_exit": true, ' \ '"wait_until_running": true, ' \ '"name": "name", ' \ '"description": "description"}' \ ']' print value nt.assert_true(value == reference)
def tearDown(self): log.debug(1, 'tearDown')
def test_list_settings(self): log.debug(1, 'test_list_settings') manager = RenderingResourceSettingsManager() params = dict() params['id'] = 'rtneuron' params['command_line'] = 'rtneuron-app.py' params['environment_variables'] = \ 'EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512' params['modules'] = 'BBP/viz/latest' params['process_rest_parameters_format'] = '--rest {$rest_hostname}:${rest_port}' params['scheduler_rest_parameters_format'] = '--rest $SLURMD_NODENAME:${rest_port}' params['project'] = 'project' params['queue'] = 'test' params['exclusive'] = False params['nb_nodes'] = 1 params['nb_cpus'] = 1 params['nb_gpus'] = 1 params['graceful_exit'] = True params['wait_until_running'] = True params['name'] = 'name' params['description'] = 'description' status = manager.create(params) nt.assert_true(status[0] == 201) params['id'] = 'livre' params['command_line'] = 'livre' params['environment_variables'] = \ 'EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512' params['modules'] = 'BBP/viz/2015.R3' params['process_rest_parameters_format'] = \ '--rest {$rest_hostname}:${rest_port}:${rest_schema}' params['scheduler_rest_parameters_format'] = \ '--rest $SLURMD_NODENAME:${rest_port}:${rest_schema}' params['project'] = 'project' params['queue'] = 'test' params['exclusive'] = False params['nb_nodes'] = 1 params['nb_cpus'] = 1 params['nb_gpus'] = 1 params['graceful_exit'] = True params['wait_until_running'] = True params['name'] = 'name' params['description'] = 'description' status = manager.create(params) nt.assert_true(status[0] == 201) status = manager.list(RenderingResourceSettingsSerializer) nt.assert_true(status[0] == 200) value = status[1] reference = '[' \ '{"id": "livre", ' \ '"command_line": "livre", ' \ '"environment_variables": ' \ '"EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512", ' \ '"modules": ' \ '"BBP/viz/2015.R3", ' \ '"process_rest_parameters_format": ' \ '"--rest {$rest_hostname}:${rest_port}:${rest_schema}", ' \ '"scheduler_rest_parameters_format": ' \ '"--rest $SLURMD_NODENAME:${rest_port}:${rest_schema}", ' \ '"project": "project", ' \ '"queue": "test", ' \ '"exclusive": false, ' \ '"nb_nodes": 1, ' \ '"nb_cpus": 1, ' \ '"nb_gpus": 1, ' \ '"graceful_exit": true, ' \ '"wait_until_running": true, ' \ '"name": "name", ' \ '"description": "description"}, ' \ '{"id": "rtneuron", ' \ '"command_line": "rtneuron-app.py", ' \ '"environment_variables": ' \ '"EQ_WINDOW_IATTR_HINT_HEIGHT=512,EQ_WINDOW_IATTR_HINT_WIDTH=512", ' \ '"modules": "BBP/viz/latest", ' \ '"process_rest_parameters_format": ' \ '"--rest {$rest_hostname}:${rest_port}", ' \ '"scheduler_rest_parameters_format": ' \ '"--rest $SLURMD_NODENAME:${rest_port}", ' \ '"project": "project", ' \ '"queue": "test", ' \ '"exclusive": false, ' \ '"nb_nodes": 1, ' \ '"nb_cpus": 1, ' \ '"nb_gpus": 1, ' \ '"graceful_exit": true, ' \ '"wait_until_running": true, ' \ '"name": "name", ' \ '"description": "description"}' \ ']' print value nt.assert_true(value == reference)