Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docker-compose.printer.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: '2'
services:
sce-printer:
container_name: sce-printer-dev
build:
context: .
dockerfile: ./printer/Dockerfile.printer.dev
ports:
# we use port 14000 as that is what the website expects
# the printing server to be running on
- 14000:14000
volumes:
- ./config:/app/config
- ./printer:/app/printer
- ./tmp:/tmp
command:
- --development
- --port=14000
- --dont-delete-pdfs
- --config-json-path=/app/config/config.json
- --dev-printer
28 changes: 28 additions & 0 deletions printer/Dockerfile.printer.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Base image from https://github.com/DrPsychick/docker-cups-airprint
# Docker images are here https://hub.docker.com/r/drpsychick/airprint-bridge/tags
FROM drpsychick/airprint-bridge:jammy

WORKDIR /app
RUN apt-get update

RUN apt install -y python3 python3-pip python3-venv jq ssh

# Create the virtual environment with Python
RUN python3 -m venv /opt/venv

# Set the virtual environment as the default Python environment
ENV PATH="/opt/venv/bin:$PATH"

COPY ./printer/requirements.txt /app/printer/requirements.txt

RUN /opt/venv/bin/pip install -r /app/printer/requirements.txt

COPY ./config/config.json /app/config/config.json

COPY ./printer/what_dev.sh /app/printer/what_dev.sh

COPY ./printer/*.py /app/printer/

EXPOSE 9000

ENTRYPOINT ["./printer/what_dev.sh"]
33 changes: 33 additions & 0 deletions printer/print_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import subprocess
import time
import logging

class PrintQueue:
_queue = []

def add(self, file_name):
self._queue.append(file_name)

def in_queue(self, file_name):
return file_name in self._queue

def feed_into_printer(self):
while True:
time.sleep(1)

if self._queue.__len__() == 0:
continue

proc = subprocess.Popen(
'lpstat -o',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)

printer_job_count = str(proc.stdout.read()).count("\n")

if printer_job_count <= 2:
logging.info("FED REQUEST INTO PRINTER")
self._queue.pop(0)
43 changes: 35 additions & 8 deletions printer/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import time
import uuid
import collector
import asyncio
from print_queue import PrintQueue

from fastapi import FastAPI, File, Form, HTTPException, UploadFile
from fastapi.middleware.cors import CORSMiddleware
Expand All @@ -17,6 +19,7 @@
from metrics import MetricsHandler


print_queue = PrintQueue()
metrics_handler = MetricsHandler.instance()
app = FastAPI()

Expand All @@ -35,7 +38,6 @@
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
logging.getLogger("uvicorn.error").setLevel(logging.WARNING)


def get_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument(
Expand All @@ -49,6 +51,12 @@ def get_args() -> argparse.Namespace:
default=9000,
help="PORT name for server to listen on. defaults to 9000",
)
parser.add_argument(
"--dev-printer",
action="store_true",
default=False,
help="specify if the development virtual printer should be used",
)
parser.add_argument(
"--config-json-path",
default="/app/config/config.json",
Expand Down Expand Up @@ -110,10 +118,11 @@ def send_file_to_printer(
maybe_page_range = f"-o page-ranges={page_range}"

# only the right printer works right now, so we default to it
PRINTER_NAME = os.environ.get("RIGHT_PRINTER_NAME")
command = f"lp -n {num_copies} {maybe_page_range} -o sides={sides} -o media=na_letter_8.5x11in -d {PRINTER_NAME} {file_path}"
PRINTER_NAME = "dev_printer" if args.dev_printer else os.environ.get("RIGHT_PRINTER_NAME")
command = f"lp -H hold -n {num_copies} {maybe_page_range} -o sides={sides} -o media=na_letter_8.5x11in -d {PRINTER_NAME} {file_path}"
metrics_handler.print_jobs_recieved.inc()
if args.development:

if args.development and not args.dev_printer:
logging.warning(
f"server is in development mode, command would've been `{command}`"
)
Expand All @@ -126,6 +135,7 @@ def send_file_to_printer(
stderr=subprocess.PIPE,
text=True,
)

print_job.wait()

if print_job.returncode != 0:
Expand All @@ -145,16 +155,14 @@ def send_file_to_printer(
# with code 0 but the output could not be parsed for a job id.
return ''


def maybe_delete_pdf(file_path):
if args.dont_delete_pdfs:
logging.info(
f"--dont-delete-pdfs is set, skipping deletion of file {file_path}"
f"--dont-delete-pdfs is set, skipping deletion of file {file_path}"
)
return
pathlib.Path(file_path).unlink()


@app.get("/healthcheck/printer")
def api():
metrics_handler.last_health_check_request.set(int(time.time()))
Expand All @@ -178,6 +186,18 @@ async def read_item(
"sides": string value from user input on clark frontend; we insert this into the lp command,
}
"""

if args.dev_printer or not args.development:
print_queue.add(file.filename)
timeout = 0
while print_queue.in_queue(file.filename):
timeout += 1

if timeout > 120:
raise Exception("/print TIMED OUT AFTER 120 SECONDS WHILE WAITING IN THE PRINTER QUEUE")

await asyncio.sleep(1)

try:
base = pathlib.Path("/tmp")
file_id = str(uuid.uuid4())
Expand All @@ -201,7 +221,7 @@ async def read_item(
status_code=500,
detail="printing failed, check logs",
)


# we have a separate __name__ check here due to how FastAPI starts
# a server. the file is first ran (where __name__ == "__main__")
Expand All @@ -212,6 +232,13 @@ async def read_item(
# the thread interacts with an instance different than the one the
# server uses
if __name__ == "server":
if args.dev_printer or not args.development:
queue_thread = threading.Thread(
target=print_queue.feed_into_printer,
daemon=True
)
queue_thread.start()

if not args.development:
# set the last time we opened an ssh tunnel to now because
# when the script runs for the first time, we did so in what.sh
Expand Down
9 changes: 9 additions & 0 deletions printer/what_dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

/root/start-cups.sh > /dev/null 2>&1 &

sleep 10

lpadmin -p dev_printer -E -v file:///dev/null

python3 /app/printer/server.py $@
Loading