コード例 #1
0
ファイル: submission.py プロジェクト: afcarl/tej
def escape_queue(s):
    """Escapes the path to a queue, e.g. preserves ~ at the begining.
    """
    if isinstance(s, PosixPath):
        s = unicode_(s)
    elif isinstance(s, bytes):
        s = s.decode('utf-8')
    if s.startswith('~/'):
        return '~/' + shell_escape(s[2:])
    else:
        return shell_escape(s)
コード例 #2
0
ファイル: submission.py プロジェクト: VisTrails/tej
def escape_queue(s):
    """Escapes the path to a queue, e.g. preserves ~ at the begining.
    """
    if isinstance(s, PosixPath):
        s = unicode_(s)
    elif isinstance(s, bytes):
        s = s.decode('utf-8')
    if s.startswith('~/'):
        return '~/' + shell_escape(s[2:])
    else:
        return shell_escape(s)
コード例 #3
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def submit(self, job_id, directory, script=None):
        """Submits a job to the queue.

        If the runtime is not there, it will be installed. If it is a broken
        chain of links, error.
        """
        if job_id is None:
            job_id = '%s_%s_%s' % (Path(directory).unicodename,
                                   self.destination['username'],
                                   make_unique_name())
        else:
            check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            queue = self._setup()

        if script is None:
            script = 'start.sh'

        # Create directory
        ret, target = self._call('%s %s' % (
                                 shell_escape(queue / 'commands/new_job'),
                                 job_id),
                                 True)
        if ret == 4:
            raise JobAlreadyExists
        elif ret != 0:
            raise JobNotFound("Couldn't create job")
        target = PosixPath(target)
        logger.debug("Server created directory %s", target)

        # Upload to directory
        try:
            scp_client = self.get_scp_client()
            scp_client.put(str(Path(directory)),
                           str(target),
                           recursive=True)
        except BaseException as e:
            try:
                self.delete(job_id)
            except BaseException:
                raise e
            raise
        logger.debug("Files uploaded")

        # Submit job
        self.check_call('%s %s %s %s' % (
                        shell_escape(queue / 'commands/submit'),
                        job_id, shell_escape(target),
                        shell_escape(script)))
        logger.info("Submitted job %s", job_id)
        return job_id
コード例 #4
0
ファイル: submission.py プロジェクト: afcarl/tej
    def submit(self, job_id, directory, script=None):
        """Submits a job to the queue.

        If the runtime is not there, it will be installed. If it is a broken
        chain of links, error.
        """
        if job_id is None:
            job_id = '%s_%s_%s' % (Path(directory).unicodename,
                                   self.destination['username'],
                                   make_unique_name())
        else:
            check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            queue = self._setup()

        if script is None:
            script = 'start.sh'

        # Create directory
        ret, target = self._call(
            '%s %s' % (shell_escape(queue / 'commands/new_job'), job_id), True)
        if ret == 4:
            raise JobAlreadyExists
        elif ret != 0:
            raise JobNotFound("Couldn't create job")
        target = PosixPath(target)
        logger.debug("Server created directory %s", target)

        # Upload to directory
        try:
            scp_client = self.get_scp_client()
            scp_client.put(str(Path(directory)), str(target), recursive=True)
        except BaseException as e:
            try:
                self.delete(job_id)
            except BaseException:
                raise e
            raise
        logger.debug("Files uploaded")

        # Submit job
        self.check_call('%s %s %s %s' %
                        (shell_escape(queue / 'commands/submit'), job_id,
                         shell_escape(target), shell_escape(script)))
        logger.info("Submitted job %s", job_id)
        return job_id
コード例 #5
0
ファイル: submission.py プロジェクト: afcarl/tej
    def _call(self, cmd, get_output):
        """Calls a command through the SSH connection.

        Remote stderr gets printed to this program's stderr. Output is captured
        and may be returned.
        """
        server_err = self.server_logger()

        chan = self.get_client().get_transport().open_session()
        try:
            logger.debug("Invoking %r%s", cmd,
                         " (stdout)" if get_output else "")
            chan.exec_command('/bin/sh -c %s' % shell_escape(cmd))
            output = b''
            while True:
                r, w, e = select.select([chan], [], [])
                if chan not in r:
                    continue  # pragma: no cover
                recvd = False
                while chan.recv_stderr_ready():
                    data = chan.recv_stderr(1024)
                    server_err.append(data)
                    recvd = True
                while chan.recv_ready():
                    data = chan.recv(1024)
                    if get_output:
                        output += data
                    recvd = True
                if not recvd and chan.exit_status_ready():
                    break
            output = output.rstrip(b'\r\n')
            return chan.recv_exit_status(), output
        finally:
            server_err.done()
            chan.close()
コード例 #6
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def status(self, job_id):
        """Gets the status of a previously-submitted job.
        """
        check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        ret, output = self._call('%s %s' % (
                                 shell_escape(queue / 'commands/status'),
                                 job_id),
                                 True)
        if ret == 0:
            directory, result = output.splitlines()
            result = result.decode('utf-8')
            return RemoteQueue.JOB_DONE, PosixPath(directory), result
        elif ret == 2:
            directory = output.splitlines()[0]
            return RemoteQueue.JOB_RUNNING, PosixPath(directory), None
        elif ret == 3:
            raise JobNotFound
        else:
            raise RemoteCommandFailure(command="commands/status",
                                       ret=ret)
コード例 #7
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def _call(self, cmd, get_output):
        """Calls a command through the SSH connection.

        Remote stderr gets printed to this program's stderr. Output is captured
        and may be returned.
        """
        server_err = self.server_logger()

        chan = self.get_client().get_transport().open_session()
        try:
            logger.debug("Invoking %r%s",
                         cmd, " (stdout)" if get_output else "")
            chan.exec_command('/bin/sh -c %s' % shell_escape(cmd))
            output = b''
            while True:
                r, w, e = select.select([chan], [], [])
                if chan not in r:
                    continue  # pragma: no cover
                recvd = False
                while chan.recv_stderr_ready():
                    data = chan.recv_stderr(1024)
                    server_err.append(data)
                    recvd = True
                while chan.recv_ready():
                    data = chan.recv(1024)
                    if get_output:
                        output += data
                    recvd = True
                if not recvd and chan.exit_status_ready():
                    break
            output = output.rstrip(b'\r\n')
            return chan.recv_exit_status(), output
        finally:
            server_err.done()
            chan.close()
コード例 #8
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def cleanup(self, kill=False):
        queue = self._get_queue()

        if queue is not None:
            # Kill jobs
            for job_id, info in self.list():
                if info['status'] == 'running':
                    if not kill:
                        raise JobStillRunning("Can't cleanup, some jobs are "
                                              "still running")
                    else:
                        logger.info("Killing running job %s", job_id)
                        self.kill(job_id)

            # Remove queue
            logger.info("Removing queue at %s", queue)
            self.check_call('rm -rf -- %s' % shell_escape(queue))

        # Remove links
        for link in self._links:
            self.check_call('rm -rf -- %s' % shell_escape(link))

        return True
コード例 #9
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def _setup(self):
        """Actually installs the runtime.
        """
        # Expands ~user in queue
        if self.queue.path[0:1] == b'/':
            queue = self.queue
        else:
            if self.queue.path[0:1] == b'~':
                output = self.check_output('echo %s' %
                                           escape_queue(self.queue))
                queue = PosixPath(output.rstrip(b'\r\n'))
            else:
                output = self.check_output('pwd')
                queue = PosixPath(output.rstrip(b'\r\n')) / self.queue
            logger.debug("Resolved to %s", queue)

        # Select runtime
        if not self.setup_runtime:
            # Autoselect
            if self._call('which qsub', False)[0] == 0:
                logger.debug("qsub is available, using runtime 'pbs'")
                runtime = 'pbs'
            else:
                logger.debug("qsub not found, using runtime 'default'")
                runtime = 'default'
        else:
            runtime = self.setup_runtime

        if self.need_runtime is not None and runtime not in self.need_runtime:
            raise ValueError("About to setup runtime %s but that wouldn't "
                             "match explicitely allowed runtimes" % runtime)

        logger.info("Installing runtime %s%s at %s",
                    runtime,
                    "" if self.setup_runtime else " (auto)",
                    self.queue)

        # Uploads runtime
        scp_client = self.get_scp_client()
        filename = pkg_resources.resource_filename('tej',
                                                   'remotes/%s' % runtime)
        scp_client.put(filename, str(queue), recursive=True)
        logger.debug("Files uploaded")

        # Runs post-setup script
        self.check_call('/bin/sh %s' % shell_escape(queue / 'commands/setup'))
        logger.debug("Post-setup script done")

        self._queue = queue
        return queue
コード例 #10
0
ファイル: submission.py プロジェクト: afcarl/tej
    def cleanup(self, kill=False):
        queue = self._get_queue()

        if queue is not None:
            # Kill jobs
            for job_id, info in self.list():
                if info['status'] == 'running':
                    if not kill:
                        raise JobStillRunning("Can't cleanup, some jobs are "
                                              "still running")
                    else:
                        logger.info("Killing running job %s", job_id)
                        self.kill(job_id)

            # Remove queue
            logger.info("Removing queue at %s", queue)
            self.check_call('rm -rf -- %s' % shell_escape(queue))

        # Remove links
        for link in self._links:
            self.check_call('rm -rf -- %s' % shell_escape(link))

        return True
コード例 #11
0
ファイル: submission.py プロジェクト: afcarl/tej
    def kill(self, job_id):
        """Kills a job on the server.
        """
        check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        ret, output = self._call(
            '%s %s' % (shell_escape(queue / 'commands/kill'), job_id), False)
        if ret == 3:
            raise JobNotFound
        elif ret != 0:
            raise RemoteCommandFailure(command='commands/kill', ret=ret)
コード例 #12
0
ファイル: submission.py プロジェクト: afcarl/tej
    def _setup(self):
        """Actually installs the runtime.
        """
        # Expands ~user in queue
        if self.queue.path[0:1] == b'/':
            queue = self.queue
        else:
            if self.queue.path[0:1] == b'~':
                output = self.check_output('echo %s' %
                                           escape_queue(self.queue))
                queue = PosixPath(output.rstrip(b'\r\n'))
            else:
                output = self.check_output('pwd')
                queue = PosixPath(output.rstrip(b'\r\n')) / self.queue
            logger.debug("Resolved to %s", queue)

        # Select runtime
        if not self.setup_runtime:
            # Autoselect
            if self._call('which qsub', False)[0] == 0:
                logger.debug("qsub is available, using runtime 'pbs'")
                runtime = 'pbs'
            else:
                logger.debug("qsub not found, using runtime 'default'")
                runtime = 'default'
        else:
            runtime = self.setup_runtime

        if self.need_runtime is not None and runtime not in self.need_runtime:
            raise ValueError("About to setup runtime %s but that wouldn't "
                             "match explicitely allowed runtimes" % runtime)

        logger.info("Installing runtime %s%s at %s", runtime,
                    "" if self.setup_runtime else " (auto)", self.queue)

        # Uploads runtime
        scp_client = self.get_scp_client()
        filename = pkg_resources.resource_filename('tej',
                                                   'remotes/%s' % runtime)
        scp_client.put(filename, str(queue), recursive=True)
        logger.debug("Files uploaded")

        # Runs post-setup script
        self.check_call('/bin/sh %s' % shell_escape(queue / 'commands/setup'))
        logger.debug("Post-setup script done")

        self._queue = queue
        return queue
コード例 #13
0
ファイル: submission.py プロジェクト: afcarl/tej
    def delete(self, job_id):
        """Deletes a job from the server.
        """
        check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        ret, output = self._call(
            '%s %s' % (shell_escape(queue / 'commands/delete'), job_id), False)
        if ret == 3:
            raise JobNotFound
        elif ret == 2:
            raise JobStillRunning
        elif ret != 0:
            raise RemoteCommandFailure(command='commands/delete', ret=ret)
コード例 #14
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def kill(self, job_id):
        """Kills a job on the server.
        """
        check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        ret, output = self._call('%s %s' % (
                                 shell_escape(queue / 'commands/kill'),
                                 job_id),
                                 False)
        if ret == 3:
            raise JobNotFound
        elif ret != 0:
            raise RemoteCommandFailure(command='commands/kill',
                                       ret=ret)
コード例 #15
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def delete(self, job_id):
        """Deletes a job from the server.
        """
        check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        ret, output = self._call('%s %s' % (
                                 shell_escape(queue / 'commands/delete'),
                                 job_id),
                                 False)
        if ret == 3:
            raise JobNotFound
        elif ret == 2:
            raise JobStillRunning
        elif ret != 0:
            raise RemoteCommandFailure(command='commands/delete',
                                       ret=ret)
コード例 #16
0
ファイル: submission.py プロジェクト: afcarl/tej
    def status(self, job_id):
        """Gets the status of a previously-submitted job.
        """
        check_jobid(job_id)

        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        ret, output = self._call(
            '%s %s' % (shell_escape(queue / 'commands/status'), job_id), True)
        if ret == 0:
            directory, result = output.splitlines()
            result = result.decode('utf-8')
            return RemoteQueue.JOB_DONE, PosixPath(directory), result
        elif ret == 2:
            directory = output.splitlines()[0]
            return RemoteQueue.JOB_RUNNING, PosixPath(directory), None
        elif ret == 3:
            raise JobNotFound
        else:
            raise RemoteCommandFailure(command="commands/status", ret=ret)
コード例 #17
0
ファイル: submission.py プロジェクト: afcarl/tej
    def list(self):
        """Lists the jobs on the server.
        """
        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        output = self.check_output('%s' %
                                   shell_escape(queue / 'commands/list'))

        job_id, info = None, None
        for line in output.splitlines():
            line = line.decode('utf-8')
            if line.startswith('    '):
                key, value = line[4:].split(': ', 1)
                info[key] = value
            else:
                if job_id is not None:
                    yield job_id, info
                job_id = line
                info = {}
        if job_id is not None:
            yield job_id, info
コード例 #18
0
ファイル: submission.py プロジェクト: VisTrails/tej
    def list(self):
        """Lists the jobs on the server.
        """
        queue = self._get_queue()
        if queue is None:
            raise QueueDoesntExist

        output = self.check_output('%s' %
                                   shell_escape(queue / 'commands/list'))

        job_id, info = None, None
        for line in output.splitlines():
            line = line.decode('utf-8')
            if line.startswith('    '):
                key, value = line[4:].split(': ', 1)
                info[key] = value
            else:
                if job_id is not None:
                    yield job_id, info
                job_id = line
                info = {}
        if job_id is not None:
            yield job_id, info
コード例 #19
0
ファイル: test_parsing.py プロジェクト: afcarl/tej
 def test_shell_escape(self):
     self.assertEqual(shell_escape("test"), "test")
     self.assertEqual(shell_escape("hello world"), '"hello world"')
     self.assertEqual(shell_escape('some"thing'), '"some\\"thing"')