Exemplo n.º 1
0
    async def handle(self, task: Task, args: list):
        """
        Method for handling compilation and scheduling of the incoming task
        :param task: incoming task
        :param args: additional arguments for compilation
        :raises CmdHandlerError
        :return: nothing
        """
        self.__set_task_log(task)

        task = await self.__streams_handler.recv_file(task)

        task.set_status(TaskStatus.COMPILING)
        await self.__io_handler.save_task(task)
        await self.__streams_handler.inform_client(task, 'Task is compiling')

        try:
            await self.__compilation_handler.handle_compilation(task, args)
            if self.__template_resolver.sched_uses_desc():
                await self.__create_task_passport(task)
            await self.__run_task(task)

            # Update HPC info on the web application side
            await self.__hpc_stats_handler.handle(task, [])
        except Exception as e:
            raise CmdHandlerError(Command.RUN, e)
Exemplo n.º 2
0
    async def save_task(self, task: Task):
        target_dir = task.path_to_task_etc(self.workdir)
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)
        task_info = os.path.join(target_dir, self.info_filename)
        await self.__async_rw.async_write_file(task_info,
                                               task.to_json(indent=4))

        return
Exemplo n.º 3
0
    def __extract_path_files_and_zip_res(self, task: Task, zip_name: str):
        path = task.get_dir_name_for_task(self.workdir)

        if not os.path.exists(path):
            raise RuntimeError(
                'Cannot get files for task {}. No directory is present for this task.'
                .format(task.get_name()))

        files = os.listdir(path)
        zip_res = os.path.join(path, zip_name)
        return path, files, zip_res
Exemplo n.º 4
0
    async def __cancel_task(self, task: Task, args: list):
        """
        Handle 'cancel' command

        :param task: related task
        :param args: additional arguments
        :return: None
        """
        cancel_command = self.__template_resolver.get_cancel_for_task(task)
        await self.exec_shell_command(cancel_command, args)
        task.set_status(TaskStatus.CANCELLED)

        return None
Exemplo n.º 5
0
    async def recv_file(self, task: Task) -> Task:
        """
        Receive incoming file from the reader channel

        :param task: related task
        :return: task
        """
        bufsize = task.get_filesize()
        in_file = await self.__in_stream.read(bufsize)
        recv_name = task.get_name()

        await self.__io_handler.write_recvd_data(task, recv_name, in_file)

        return task
Exemplo n.º 6
0
    async def inform_client(self,
                            task: Task,
                            message: str,
                            error: Exception = None) -> None:
        """
        Send information to the server using async writer channel

        :param task: related task
        :param error: related error message
        :param message: message to send
        :return: nothing
        """
        to_send = {'task_info': {}, 'message': '', 'error': ''}

        if task is not None:
            # Add info about the received task
            task_msg = {
                'name': task.get_name(),
                'username': task.get_user(),
                'status': task.get_str_status()
            }
            to_send['task_info'] = task_msg

        to_send['message'] = message

        levelname = LogLevel.DEBUG
        if error is not None and error != 'None':
            error = '{}'.format(error)
            idx = error.find(self.__ERROR_DESC_START)
            if idx >= 0:
                error = error[idx + len(self.__ERROR_DESC_START):]

            to_send['error'] = '{}'.format(error)
            to_send['task_info']['status'] = 'ERROR'
            levelname = LogLevel.ERROR
        self.__log_writer.log('Request response: {}'.format(
            json.dumps(to_send, indent=4)),
                              level=levelname)

        try:
            # Sending response to CKD web application
            self.__out_stream.write(json.dumps(to_send, indent=4).encode())
            await self.__out_stream.drain()
        except Exception as e:
            self.__log_writer.log(
                'Error occurred while responding to the CKD application: {}'.
                format(e))
        self.__log_writer.log('Response sent.', level=LogLevel.DEBUG)
Exemplo n.º 7
0
    async def write_recvd_data(self, task: Task, recv_name: str,
                               recvd_data: bytes):
        # Create directory for task files if it doesn't exist
        srcdir = task.path_to_task_src(self.workdir)
        if not os.path.exists(srcdir):
            os.makedirs(srcdir)

        # Write incoming file on disk
        recv_file = os.path.join(srcdir, recv_name)
        await self.__async_rw.async_write_file(recv_file, recvd_data)

        if task.is_file_archive():
            await self.__executor.async_execution(self.__handle_archive, task,
                                                  srcdir, recv_file)

        return
Exemplo n.º 8
0
    def create_cmake_lists(self, task: Task):
        """
        Generates CMakeLists.txt to make an archive into the CMake project

        :param task: task to handle
        :return: None
        """
        path = task.path_to_task_src(self.__workdir)
        cmake_lists_filename = os.path.join(path, self.__C_MAKE_LISTS_TXT__)

        main_file = self.__get_main_file_in_project(path)

        task_name = task.get_name()
        file_contents = [
            'cmake_minimum_required(VERSION {})'.format(self.__cmake_version),
            'project({})'.format(task_name),
            'SET(CMAKE_BUILD_TYPE Release)',
        ]

        extension = main_file.split('.')[-1]

        file_contents.append('file(GLOB SOURCES "./*.{}")'.format(extension))

        file_contents.append(' '.join(
            ['add_executable('.format(task_name), '${SOURCES})']))

        dirs = self.__filter_dirs(path)

        include_dirs = list(filter(lambda x: 'include' in x, dirs))
        include_dirs = set(include_dirs)

        file_contents.append('include_directories({})'.format(
            ', '.join(include_dirs)))

        dirs = set(dirs) - include_dirs

        for dir_name in dirs:
            file_contents.append('add_subdirectory({})'.format(dir_name))

        file_contents = '\n'.join(file_contents)
        file_contents = correct_line_breaks(file_contents)

        with open(cmake_lists_filename, 'w') as cmake_lists_file:
            cmake_lists_file.write(file_contents)
Exemplo n.º 9
0
    def parse_net_command(json_bytes_with_sep):
        json_string = json_bytes_with_sep.rstrip(b'\0').decode()
        dct = json.loads(json_string)

        source = dct['source'].rstrip('/')
        cmd = Command(dct['cmd'])

        if dct['cmd'] != 'hpc_stats':
            return source, cmd, Task(dct['task_info']), dct['args']
        else:
            return source, cmd, None, None
Exemplo n.º 10
0
    def __get_compile_cmds(self, task: Task, args: list):
        """
        Get compilation command to compile all of the task source files.

        :param task: related task
        :param args: additional arguments
        :return: list of compilation commands
        """
        compiler = task.get_compiler()
        if '' != compiler:
            bin_path = task.path_to_task_bin(self.__workdir)
            if not os.path.exists(bin_path):
                os.makedirs(bin_path)

            path = task.path_to_task_src(self.__workdir)
            if task.is_file_archive():
                if self.__cmake_handler is not None and task.uses_cmake():
                    if not self.__cmake_handler.is_cmake_target(path):
                        self.__cmake_handler.create_cmake_lists(task)
                    commands = self.__cmake_handler.get_compilation_commands_using_cmake(
                        task)
                else:
                    commands = self.__no_cmake_compile_cmd(
                        compiler, task, args)
            else:
                commands = self.__get_compile_cmd_for_single_file(
                    compiler, task, args)

            self.__log_writer.log(json.dumps(commands, indent=4),
                                  level=LogLevel.DEBUG)
            return commands
        else:
            raise RuntimeError('No compiler is set for the task: {}'.format(
                task.get_name()))
Exemplo n.º 11
0
    async def get_sources(self, task: Task):
        zip_name = 'sources.zip'
        path, files, zip_res = self.__extract_path_files_and_zip_res(
            task, zip_name)
        if zip_name not in files:
            path = task.path_to_task_src(self.workdir)
            files = list(map(lambda x: os.path.join(path, x),
                             os.listdir(path)))

            await self.__executor.async_execution(self.__write_zip_file, files,
                                                  zip_res)

        return zip_res
Exemplo n.º 12
0
    async def write_task_passport(self, task: Task, passport: str):
        path_to_passport = task.path_to_task_etc(self.workdir)
        if not os.path.exists(path_to_passport):
            os.makedirs(path_to_passport)

        path_to_passport = os.path.join(path_to_passport,
                                        self.passport_filename)

        passport = correct_line_breaks(passport)

        await self.__async_rw.async_write_file(path_to_passport, passport)

        return path_to_passport
Exemplo n.º 13
0
    def get_compilation_commands_using_cmake(self, task: Task):
        """
        Constructs commands to build CMake project and sets target executable name for task.
        For now supports only project build using Unix Makefiles.

        :param task: task to handle
        :return: command list to build CMake project
        """
        path = task.path_to_task_src(self.__workdir)
        bin_path = task.path_to_task_bin(self.__workdir)

        if not os.path.exists(bin_path):
            os.makedirs(bin_path)

        commands = [
            # invoking cmake in the 'bin' directory so that all of the generated files are inside 'bin' directory
            'cmake {} --warn-uninitialized --warn-unused-vars -Wno-dev'.format(
                path),
            # invoking build through the CMake build tool using appropriate tool for the system
            'cmake --build .',
        ]
        self.__log_writer.log(json.dumps(commands, indent=4), LogLevel.DEBUG)

        with open(os.path.join(path, self.__C_MAKE_LISTS_TXT__),
                  'r') as cmake_file:
            lines = cmake_file.read().splitlines()

        lines = list(filter(lambda x: 'project' in x, lines))
        # line = 'project(project_name)'
        lines = list(filter(lambda x: len(x) > 0, lines))
        lines = list(map(lambda x: re.split(r'[() ]', x), lines))
        self.__log_writer.log('LINES: {}'.format(lines))
        bin_name = os.path.join(bin_path, lines[0][1])
        task.set_bin_name(bin_name)

        return commands
Exemplo n.º 14
0
    def __handle_archive(task: Task, curdir: str, recv_file: str):
        before = set(os.listdir(curdir))
        if '.zip' in task.get_filename():
            with zipfile.ZipFile(recv_file, mode='r') as zip_arc:
                arc_type = 'zip'
                zip_arc.extractall(path=curdir)
        else:
            with tarfile.open(name=recv_file, mode='r:*') as tar:
                arc_type = 'tar'
                tar.extractall(path=curdir)
        after = set(os.listdir(curdir))
        if after - (after ^ before) == set():
            # No changes in the directory
            raise RuntimeError('No extraction for {} archive'.format(arc_type))

        # There is no need for the archive to stay any longer
        os.remove(recv_file)
Exemplo n.º 15
0
    def get_passport(self, task: Task):
        template = self.__sched.get_passport_template()

        template = template.splitlines()
        if 'mpi' in task.get_compiler().lower():
            template = self.__mpi_adapt_passport_template(
                template, '__NO_MPI__', '__MPI__')
        else:
            template = self.__mpi_adapt_passport_template(
                template, '__MPI__', '__NO_MPI__')

        template = '\n'.join(template)
        passport = self.__substitute_template_params(template, task)

        self.__log_writer.log('PASSPORT:\n{}'.format(passport),
                              level=LogLevel.DEBUG)

        return passport
Exemplo n.º 16
0
    def __get_flat_archive_files(self, c_compiler, task: Task):
        """
        Get files list relevant for compilation

        :param c_compiler: whether the program would be compiled using C/C++ compiler
        :param task: task to handle
        :return: source files list
        """
        path = task.path_to_task_src(self.__workdir)
        dirfiles = os.listdir(path)
        if c_compiler:
            files = list(
                filter(lambda x: '.cxx' in x or '.cpp' in x or '.c' in x,
                       dirfiles))
        else:
            files = list(filter(lambda x: '.f' in x, dirfiles))
        files = list(map(lambda x: os.path.join(path, x), files))
        files = ' '.join(files)
        return files
Exemplo n.º 17
0
    async def handle_compilation(self, task: Task, args: list):
        task.set_bin_name(
            os.path.join(task.path_to_task_bin(self.__workdir),
                         task.get_name() + '.out'))

        compilation_commands = self.__get_compile_cmds(task, args)

        compilation_output = await self.__executor.async_exec_cmds_with_wrapping(
            commands=compilation_commands,
            dir_to_use=task.path_to_task_bin(self.__workdir),
        )

        compilation_log_file = os.path.join(
            task.get_dir_name_for_task(self.__workdir), 'compilation.log')
        with open(compilation_log_file, 'w') as output_file:
            output_file.write(compilation_output)

        return
Exemplo n.º 18
0
    async def restore_task(self, task: Task):
        task_info = os.path.join(task.path_to_task_etc(self.workdir),
                                 self.info_filename)
        task = Task.from_json(await self.__async_rw.async_read_file(task_info))

        return task
Exemplo n.º 19
0
    def __init_templ_dct(self, templ_dct, task: Task):
        """
        Function to initialize template dictionary with methods of the related Task object

        :param task: related task
        :return: nothing
        """
        templ_dct['__procnum__'] = task.get_procnum()
        templ_dct['__walltime__'] = task.get_walltime()
        templ_dct['__memory__'] = task.get_memory()
        templ_dct['__filename__'] = task.get_filename()
        templ_dct['__descname__'] = task.get_passport_name()
        templ_dct['__jobid__'] = task.get_jobid()
        templ_dct['__name__'] = task.get_name()
        templ_dct['__user__'] = task.get_user()
        templ_dct['__taskdir__'] = task.get_dir_name_for_task(self.workdir)
        templ_dct['__binname__'] = task.get_bin_name()
        templ_dct['__logname__'] = task.get_log_name()
        templ_dct['__workdir__'] = self.__get_workdir()