Synchronous part of _new_job. Creates needed directories, copy files, and starts the container.

def __new_job_sync(self, message, future_results):
        """ Synchronous part of _new_job. Creates needed directories, copy files, and starts the container. """
        course_id = message.course_id
        task_id = message.task_id

        debug = message.debug
        environment_name = message.environment
        enable_network = message.enable_network
        time_limit = message.time_limit
        hard_time_limit = message.hard_time_limit or time_limit * 3
        mem_limit = message.mem_limit

        course_fs = self.tasks_fs.from_subfolder(course_id)
        task_fs = course_fs.from_subfolder(task_id)

        if not course_fs.exists() or not task_fs.exists():
            self._logger.warning("Task %s/%s unavailable on this agent", course_id, task_id)
            raise CannotCreateJobException('Task unavailable on agent. Please retry later, the agents should synchronize soon. '
                             'If the error persists, please contact your course administrator.')

        # Check for realistic memory limit value
        if mem_limit < 20:
            mem_limit = 20
        elif mem_limit > self._max_memory_per_slot:
            self._logger.warning("Task %s/%s ask for too much memory (%dMB)! Available: %dMB", course_id, task_id,
                                 mem_limit, self._max_memory_per_slot)
            raise CannotCreateJobException('Not enough memory on agent (available: %dMB). Please contact your course administrator.' % self._max_memory_per_slot)

        if environment_name not in self._containers:
            self._logger.warning("Task %s/%s ask for an unknown environment %s (not in aliases)", course_id, task_id,
                                 environment_name)
            raise CannotCreateJobException('Unknown container. Please contact your course administrator.')

        environment = self._containers[environment_name]["id"]

        ports_needed = self._containers[environment_name]["ports"]

        if debug == "ssh" and 22 not in ports_needed:
            ports_needed.append(22)

        ports = {}
        if len(ports_needed) > 0:
            time_limit = 30 * 60
            hard_time_limit = 30 * 60
        for p in ports_needed:
            if len(self._external_ports) == 0:
                self._logger.warning("User asked for a port but no one are available")
                raise CannotCreateJobException('No ports are available right now. Please retry later.')
            ports[p] = self._external_ports.pop()

        # Create directories for storing all the data for the job
        try:
            container_path = tempfile.mkdtemp(dir=self._tmp_dir)
        except Exception as e:
            self._logger.error("Cannot make container temp directory! %s", str(e), exc_info=True)
            for p in ports:
                self._external_ports.add(ports[p])
            raise CannotCreateJobException('Cannot make container temp directory.')

        task_path = path_join(container_path, 'task')  # tmp_dir/id/task/
        course_path = path_join(container_path, 'course')

        sockets_path = path_join(container_path, 'sockets')  # tmp_dir/id/socket/
        student_path = path_join(task_path, 'student')  # tmp_dir/id/task/student/
        systemfiles_path = path_join(task_path, 'systemfiles')  # tmp_dir/id/task/systemfiles/

        course_common_path = path_join(course_path, 'common')
        course_common_student_path = path_join(course_path, 'common', 'student')

        # Create the needed directories
        os.mkdir(sockets_path)
        os.chmod(container_path, 0o777)
        os.chmod(sockets_path, 0o777)
        os.mkdir(course_path)

        # TODO: avoid copy
        task_fs.copy_from(None, task_path)
        os.chmod(task_path, 0o777)

        if not os.path.exists(student_path):
            os.mkdir(student_path)
            os.chmod(student_path, 0o777)

        # Copy common and common/student if needed
        # TODO: avoid copy
        if course_fs.from_subfolder("$common").exists():
            course_fs.from_subfolder("$common").copy_from(None, course_common_path)
        else:
            os.mkdir(course_common_path)

        if course_fs.from_subfolder("$common").from_subfolder("student").exists():
            course_fs.from_subfolder("$common").from_subfolder("student").copy_from(None, course_common_student_path)
        else:
            os.mkdir(course_common_student_path)

        # Run the container
        try:
            container_id = self._docker.sync.create_container(environment, enable_network, mem_limit, task_path,
                                                              sockets_path, course_common_path,
                                                              course_common_student_path, ports)
        except Exception as e:
            self._logger.warning("Cannot create container! %s", str(e), exc_info=True)
            shutil.rmtree(container_path)
            for p in ports:
                self._external_ports.add(ports[p])
            raise CannotCreateJobException('Cannot create container.')

        # Store info
        self._containers_running[container_id] = message, container_path, future_results
        self._container_for_job[message.job_id] = container_id
        self._student_containers_for_job[message.job_id] = set()

        if len(ports) != 0:
            self._assigned_external_ports[container_id] = list(ports.values())

        try:
            # Start the container
            self._docker.sync.start_container(container_id)
        except Exception as e:
            self._logger.warning("Cannot start container! %s", str(e), exc_info=True)
            shutil.rmtree(container_path)
            for p in ports:
                self._external_ports.add(ports[p])

            raise CannotCreateJobException('Cannot start container')

        return {
            "job_id": message.job_id,
            "container_id": container_id,
            "inputdata": message.inputdata,
            "debug": debug,
            "ports": ports,
            "orig_env": environment_name,
            "orig_memory_limit": mem_limit,
            "orig_time_limit": time_limit,
            "orig_hard_time_limit": hard_time_limit,
            "sockets_path": sockets_path,
            "student_path": student_path,
            "systemfiles_path": systemfiles_path,
            "course_common_student_path": course_common_student_path
        }