Example #1
0
def printer_create():
    data = request.json
    if not data:
        return abort(400)
    ip = data.get("ip", None)
    name = data.get("name", None)
    if (not ip or not name or re.match(
            r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:?\d{0,5}$", ip) is None):
        return abort(400)
    if printers.get_printer(ip) is not None:
        return abort(409)
    hostname = network.get_avahi_hostname(ip)
    printer = drivers.get_printer_instance({
        "hostname": hostname,
        "ip": ip,
        "name": name,
        "client": "octoprint",  # TODO make this more generic
    })
    printer.sniff()
    network_devices.upsert_network_device(ip=ip,
                                          retry_after=None,
                                          disabled=False)
    printers.add_printer(
        name=name,
        hostname=hostname,
        ip=ip,
        client=printer.client_name(),
        client_props={
            "version": printer.client.version,
            "connected": printer.client.connected,
            "read_only": printer.client.read_only,
        },
    )
    return "", 201
Example #2
0
def printer_change_connection(uuid):
    # TODO this has to be streamlined, octoprint sometimes cannot handle two connect commands at once
    try:
        uuidmodule.UUID(uuid, version=4)
    except ValueError:
        return abort(make_response("", 400))
    printer = printers.get_printer(uuid)
    if printer is None:
        return abort(make_response("", 404))
    data = request.json
    if not data:
        return abort(make_response("", 400))
    state = data.get("state", None)
    printer_inst = clients.get_printer_instance(printer)
    if state == "online":
        r = printer_inst.connect_printer()
        return (("", 204) if r else
                ("Cannot change printer's connection state to online", 500))
    elif state == "offline":
        r = printer_inst.disconnect_printer()
        return (("", 204) if r else
                ("Cannot change printer's connection state to offline", 500))
    else:
        return abort(make_response("", 400))
    return "", 204
Example #3
0
def printer_detail(ip):
    fields = request.args.get("fields").split(",") if request.args.get(
        "fields") else []
    printer = printers.get_printer(ip)
    if printer is None:
        return abort(404)
    return jsonify(make_printer_response(printer, fields))
Example #4
0
def printer_modify_job(uuid):
    # TODO allow users to pause/cancel only their own prints via printjob_id
    # And allow admins to pause/cancel anything
    # but that means creating a new tracking of current jobs on each printer
    # and does not handle prints issued by bypassing Karmen Hub
    # Alternative is to log who modified the current job into an admin-accessible eventlog
    # See https://trello.com/c/uiv0luZ8/142 for details
    try:
        uuidmodule.UUID(uuid, version=4)
    except ValueError:
        return abort(make_response("", 400))
    printer = printers.get_printer(uuid)
    if printer is None:
        return abort(make_response("", 404))
    data = request.json
    if not data:
        return abort(make_response("", 400))
    action = data.get("action", None)
    if not action:
        return abort(make_response("", 400))
    printer_inst = clients.get_printer_instance(printer)
    try:
        if printer_inst.modify_current_job(action):
            user = get_current_user()
            app.logger.info(
                "User %s successfully issued a modification (%s) of current job on printer %s",
                user["uuid"],
                action,
                uuid,
            )
            return "", 204
        return abort(make_response("", 409))
    except clients.utils.PrinterClientException as e:
        return abort(make_response(jsonify(message=str(e)), 400))
Example #5
0
def add_printjob(**job):
    'creates a printjob returning the id of the newly created job'

    if 'uuid' in job:
        raise ValueError("Cannot add a printjob with an already set UUID.")

    printer = get_printer(job["printer_uuid"])
    if not printer:
        raise ValueError(f"The printer {job['printer_uuid']} does not exist.")
    if printer["organization_uuid"] != job["organization_uuid"]:
        raise ValueError(f"The printer does not belong to the organization.")
    if job.get("gcode_data", None) and job["gcode_data"].get("uuid", None):
        if job["gcode_uuid"] != job["gcode_data"]["uuid"]:
            raise ValueError("printjob['gcode_uuid'] does not match printjob['gcode_data']['uuid']")

    # FIXME: printjob should not contain organization_uuid (it is already in printer_uuid)
    job['uuid'] = guid.uuid4()
    with get_connection() as connection:
        cursor = connection.cursor()
        cursor.execute(
            "INSERT INTO printjobs (uuid, gcode_uuid, organization_uuid, printer_uuid, gcode_data, printer_data, user_uuid) values (%s, %s, %s, %s, %s, %s, %s) RETURNING uuid",
            (
                job["uuid"],
                job["gcode_uuid"],
                job["organization_uuid"],
                job["printer_uuid"],
                psycopg2.extras.Json(job.get("gcode_data", None)),
                psycopg2.extras.Json(job.get("printer_data", None)),
                job.get("user_uuid", None),
            ),
        )
        data = cursor.fetchone()
        cursor.close()
        return data[0]
Example #6
0
def printer_delete(ip):
    printer = printers.get_printer(ip)
    if printer is None:
        return abort(404)
    printers.delete_printer(ip)
    for device in network_devices.get_network_devices(printer["ip"]):
        device["disabled"] = True
        network_devices.upsert_network_device(**device)
    return "", 204
Example #7
0
def printer_delete(uuid):
    try:
        uuidmodule.UUID(uuid, version=4)
    except ValueError:
        return abort(make_response("", 400))
    printer = printers.get_printer(uuid)
    if printer is None:
        return abort(make_response("", 404))
    printers.delete_printer(uuid)
    return "", 204
Example #8
0
def printer_webcam_snapshot(uuid):
    """
    Instead of direct streaming from the end-devices, we are deferring
    the video-like feature to the clients. This (in case of MJPEG) brings
    significant performance gains throughout the whole pipeline.

    This endpoint serves as a redis-backed (due to multithreaded production setup
    with uwsgi) microcache of latest captured image from any
    given printer. New snapshot is requested, but the old one is served to
    the client. In case of the first request, a 202 is returned and the client
    should ask again. By asking periodically for new snapshots, the client
    can emulate a video-like experience. Since we have no sound, this should be
    fine.
    """
    try:
        uuidmodule.UUID(uuid, version=4)
    except ValueError:
        return abort(make_response("", 400))
    printer = printers.get_printer(uuid)
    if printer is None:
        return abort(make_response("", 404))
    printer_inst = clients.get_printer_instance(printer)
    if printer_inst.client_info.webcam is None:
        return abort(make_response("", 404))
    snapshot_url = printer_inst.client_info.webcam.get("snapshot")
    if snapshot_url is None:
        return abort(make_response("", 404))

    # process current future if done
    if FUTURES_MICROCACHE.get(uuid) and FUTURES_MICROCACHE.get(uuid).done():
        WEBCAM_MICROCACHE[uuid] = FUTURES_MICROCACHE[uuid].result()
        try:
            del FUTURES_MICROCACHE[uuid]
        except Exception:
            # that's ok, probably a race condition
            pass
    # issue a new future if not present
    if not FUTURES_MICROCACHE.get(uuid):
        FUTURES_MICROCACHE[uuid] = executor.submit(_get_webcam_snapshot,
                                                   snapshot_url)

    if WEBCAM_MICROCACHE.get(uuid) is not None:
        response = WEBCAM_MICROCACHE.get(uuid)
        return (
            response.content,
            200,
            {
                "Content-Type": response.headers.get("content-type",
                                                     "image/jpeg")
            },
        )
    # There should be a future running, if the client retries, they should
    # eventually get a snapshot.
    # We don't want to end with an error here, so the clients keep retrying
    return "", 202
Example #9
0
def printer_detail(uuid):
    try:
        uuidmodule.UUID(uuid, version=4)
    except ValueError:
        return abort(make_response("", 400))
    fields = request.args.get("fields").split(",") if request.args.get(
        "fields") else []
    printer = printers.get_printer(uuid)
    if printer is None:
        return abort(make_response("", 404))
    return jsonify(make_printer_response(printer, fields))
Example #10
0
def get_printer_inst(org_uuid, uuid):
    validate_uuid(uuid)
    printer = printers.get_printer(uuid)
    if printer is None or printer.get("organization_uuid") != org_uuid:
        return abort(make_response(jsonify(message="Not found"), 404))
    network_client = network_clients.get_network_client(
        printer["network_client_uuid"])
    printer_data = dict(network_client)
    printer_data.update(dict(printer))
    printer_inst = clients.get_printer_instance(printer_data)
    return printer_inst
Example #11
0
def check_printer(printer_uuid):
    app.logger.debug("Checking printer %s" % printer_uuid)
    raw_printer = printers.get_printer(printer_uuid)
    # todo: The `get_printer` method should raise an exception instead of returning None
    if raw_printer is None:
        app.logger.info(
            "Printer was deleted after it was scheduled for update.")
        return
    raw_client = network_clients.get_network_client(
        raw_printer["network_client_uuid"])
    printer_data = dict(raw_client)
    printer_data.update(raw_printer)
    printer = clients.get_printer_instance(printer_data)
    # websocket printers are not expected to change
    if printer.protocol in ["http", "https"]:
        if printer.hostname is not None:
            current_ip = network.get_avahi_address(printer.hostname)
            if current_ip is not None and current_ip != printer.ip:
                printer.ip = current_ip
                printer.update_network_base()
        hostname = network.get_avahi_hostname(printer.ip)
        if hostname is not None and hostname != printer.hostname:
            printer.hostname = hostname
            printer.update_network_base()
    now = datetime.now()
    if now.minute % 15 == 0 and printer.client_info.connected:
        printer.sniff()
        printer.karmen_sniff()
    else:
        printer.is_alive()

    if (printer.client_info.pill_info and printer.client_info.pill_info.get(
            "update_status", None) is not None):
        printer.karmen_sniff()

    if printer.hostname != raw_client.get(
            "hostname") or printer.ip != raw_client.get("ip"):
        network_clients.update_network_client(
            uuid=raw_client["uuid"],
            hostname=printer.hostname,
            ip=printer.ip,
        )
    printers.update_printer(
        uuid=printer.uuid,
        client_props={
            "version": printer.client_info.version,
            "connected": printer.client_info.connected,
            "access_level": printer.client_info.access_level,
            "api_key": printer.client_info.api_key,
            "webcam": printer.client_info.webcam,
            "plugins": printer.client_info.plugins,
            "pill_info": printer.client_info.pill_info,
        },
    )
Example #12
0
def printer_delete(org_uuid, uuid):
    validate_uuid(uuid)
    printer = printers.get_printer(uuid)
    if printer is None or printer.get("organization_uuid") != org_uuid:
        return abort(make_response(jsonify(message="Not found"), 404))
    printers.delete_printer(uuid)
    network_client_records = printers.get_printers_by_network_client_uuid(
        printer["network_client_uuid"])
    if len(network_client_records) == 0:
        network_clients.delete_network_client(printer["network_client_uuid"])
    return "", 204
Example #13
0
def printjob_create():
    data = request.json
    if not data:
        return abort(make_response("", 400))
    gcode_id = data.get("gcode", None)
    printer_uuid = data.get("printer", None)
    if not gcode_id or not printer_uuid:
        return abort(make_response("", 400))
    printer = printers.get_printer(printer_uuid)
    if printer is None:
        return abort(make_response("", 404))
    gcode = gcodes.get_gcode(gcode_id)
    if gcode is None:
        return abort(make_response("", 404))
    try:
        printer_inst = clients.get_printer_instance(printer)
        uploaded = printer_inst.upload_and_start_job(gcode["absolute_path"],
                                                     gcode["path"])
        if not uploaded:
            return abort(
                make_response(
                    jsonify(message="Cannot upload the g-code to the printer"),
                    500))
        printjob_id = printjobs.add_printjob(
            gcode_id=gcode["id"],
            printer_uuid=printer["uuid"],
            user_uuid=get_current_user()["uuid"],
            gcode_data={
                "id": gcode["id"],
                "filename": gcode["filename"],
                "size": gcode["size"],
                "available": True,
            },
            printer_data={
                "ip": printer["ip"],
                "port": printer["port"],
                "hostname": printer["hostname"],
                "name": printer["name"],
                "client": printer["client"],
            },
        )
        return (
            jsonify({
                "id": printjob_id,
                "user_uuid": get_current_user()["uuid"]
            }),
            201,
        )
    except clients.utils.PrinterClientException:
        return abort(make_response("", 409))
Example #14
0
 def test_patch(self):
     with app.test_client() as c:
         c.set_cookie("localhost", "access_token_cookie", TOKEN_ADMIN)
         response = c.patch(
             "/printers/%s" % self.uuid,
             headers={"x-csrf-token": TOKEN_ADMIN_CSRF},
             json={
                 "name": "random-test-printer-name",
                 "protocol": "https"
             },
         )
         self.assertEqual(response.status_code, 200)
         p = printers.get_printer(self.uuid)
         self.assertEqual(p["name"], "random-test-printer-name")
         self.assertEqual(p["protocol"], "https")
Example #15
0
 def test_patch_api_keychange(self, mock_session_get):
     with app.test_client() as c:
         c.set_cookie("localhost", "access_token_cookie", TOKEN_ADMIN)
         response = c.patch(
             "/printers/%s" % self.uuid,
             headers={"x-csrf-token": TOKEN_ADMIN_CSRF},
             json={
                 "name": "random-test-printer-name",
                 "api_key": "1234",
             },
         )
         self.assertEqual(response.status_code, 200)
         p = printers.get_printer(self.uuid)
         self.assertEqual(p["client_props"]["api_key"], "1234")
         self.assertEqual(mock_session_get.call_count, 1)
Example #16
0
def printer_webcam(ip):
    # This is very inefficient and should not be used in production. Use the nginx
    # redis based proxy pass instead
    # TODO maybe we can drop this in the dev env as well
    printer = printers.get_printer(ip)
    if printer is None:
        return abort(404)
    printer_inst = drivers.get_printer_instance(printer)
    webcam = printer_inst.webcam()
    if "stream" not in webcam:
        return abort(404)
    req = requests.get(webcam["stream"], stream=True)
    return Response(
        stream_with_context(req.iter_content()),
        content_type=req.headers["content-type"],
    )
Example #17
0
def save_printer_data(**kwargs):
    has_record = printers.get_printer(kwargs["ip"])
    if has_record is None and not kwargs["client_props"]["connected"]:
        return
    if has_record is None:
        printers.add_printer(
            **{
                "name": None,
                "client_props": {"connected": False, "version": {}, "read_only": True},
                **kwargs,
            }
        )
    else:
        printers.update_printer(
            **{**has_record, **kwargs, **{"name": has_record["name"]}}
        )
Example #18
0
def printer_modify_job(ip):
    printer = printers.get_printer(ip)
    if printer is None:
        return abort(404)
    data = request.json
    if not data:
        return abort(400)
    action = data.get("action", None)
    if not action:
        return abort(400)
    printer_inst = drivers.get_printer_instance(printer)
    try:
        if printer_inst.modify_current_job(action):
            return "", 204
        return "", 409
    except drivers.utils.PrinterDriverException as e:
        return abort(400, e)
Example #19
0
def check_printer(printer_uuid):
    app.logger.debug("Checking printer %s" % printer_uuid)
    raw_printer = printers.get_printer(printer_uuid)
    raw_client = network_clients.get_network_client(
        raw_printer["network_client_uuid"])
    printer_data = dict(raw_client)
    printer_data.update(raw_printer)
    printer = clients.get_printer_instance(printer_data)
    # websocket printers are not expected to change
    if printer.protocol in ["http", "https"]:
        if printer.hostname is not None:
            current_ip = network.get_avahi_address(printer.hostname)
            if current_ip is not None and current_ip != printer.ip:
                printer.ip = current_ip
                printer.update_network_base()
        hostname = network.get_avahi_hostname(printer.ip)
        if hostname is not None and hostname != printer.hostname:
            printer.hostname = hostname
            printer.update_network_base()
    now = datetime.now()
    if now.minute % 15 == 0 and printer.client_info.connected:
        printer.sniff()
    else:
        printer.is_alive()

    if printer.hostname != raw_client.get(
            "hostname") or printer.ip != raw_client.get("ip"):
        network_clients.update_network_client(
            uuid=raw_client["uuid"],
            hostname=printer.hostname,
            ip=printer.ip,
        )

    printers.update_printer(
        uuid=printer.uuid,
        client_props={
            "version": printer.client_info.version,
            "connected": printer.client_info.connected,
            "access_level": printer.client_info.access_level,
            "api_key": printer.client_info.api_key,
            "webcam": printer.client_info.webcam,
            "plugins": printer.client_info.plugins,
        },
    )
Example #20
0
 def test_patch_printer_props(self):
     with app.test_client() as c:
         c.set_cookie("localhost", "access_token_cookie", TOKEN_ADMIN)
         response = c.patch(
             "/printers/%s" % self.uuid,
             headers={"x-csrf-token": TOKEN_ADMIN_CSRF},
             json={
                 "name": "random-test-printer-name",
                 "printer_props": {
                     "filament_type": "PETG",
                     "filament_color": "žluťoučká",
                     "random": "key",
                 },
             },
         )
         self.assertEqual(response.status_code, 200)
         p = printers.get_printer(self.uuid)
         self.assertEqual(p["printer_props"]["filament_type"], "PETG")
         self.assertEqual(p["printer_props"]["filament_color"], "žluťoučká")
         self.assertTrue("random" not in p["printer_props"])
Example #21
0
 def test_list(self):
     with app.test_client() as c:
         c.set_cookie("localhost", "access_token_cookie", TOKEN_USER)
         response = c.get(
             "/organizations/%s/printjobs" % UUID_ORG,
             headers={"x-csrf-token": TOKEN_USER_CSRF},
         )
         self.assertEqual(response.status_code, 200)
         self.assertTrue("items" in response.json)
         if len(response.json["items"]) < 200:
             self.assertTrue("next" not in response.json)
         self.assertTrue(len(response.json["items"]) >= 2)
         self.assertTrue("uuid" in response.json["items"][0])
         self.assertTrue("user_uuid" in response.json["items"][0])
         self.assertTrue("username" in response.json["items"][0])
         self.assertTrue("gcode_data" in response.json["items"][0])
         self.assertTrue("printer_data" in response.json["items"][0])
         self.assertTrue("started" in response.json["items"][0])
         for item in response.json["items"]:
             printer = printers.get_printer(item["printer_uuid"])
             self.assertEqual(printer["organization_uuid"], UUID_ORG)
Example #22
0
def printjob_create():
    data = request.json
    if not data:
        return abort(400)
    gcode_id = data.get("gcode", None)
    printer_ip = data.get("printer", None)
    if not gcode_id or not printer_ip:
        return abort(400)
    printer = printers.get_printer(printer_ip)
    if printer is None:
        return abort(404)
    gcode = gcodes.get_gcode(gcode_id)
    if gcode is None:
        return abort(404)
    try:
        printer_inst = drivers.get_printer_instance(printer)
        uploaded = printer_inst.upload_and_start_job(gcode["absolute_path"],
                                                     gcode["path"])
        if not uploaded:
            return abort(500, "Cannot upload the g-code to the printer")
        printjob_id = printjobs.add_printjob(
            gcode_id=gcode["id"],
            printer_ip=printer["ip"],
            gcode_data={
                "id": gcode["id"],
                "filename": gcode["filename"],
                "size": gcode["size"],
                "available": True,
            },
            printer_data={
                "ip": printer["ip"],
                "name": printer["name"],
                "client": printer["client"],
            },
        )
        return jsonify({"id": printjob_id}), 201
    except drivers.utils.PrinterDriverException:
        return abort(409)
Example #23
0
def printer_patch(ip):
    printer = printers.get_printer(ip)
    if printer is None:
        return abort(404)
    data = request.json
    if not data:
        return abort(400)
    name = data.get("name", None)
    if not name:
        return abort(400)
    printer_inst = drivers.get_printer_instance(printer)
    printers.update_printer(
        name=name,
        hostname=printer_inst.hostname,
        ip=printer_inst.ip,
        client=printer_inst.client_name(),
        client_props={
            "version": printer_inst.client.version,
            "connected": printer_inst.client.connected,
            "read_only": printer_inst.client.read_only,
        },
    )
    return "", 204
Example #24
0
def printjob_create(org_uuid):
    data = request.json
    if not data:
        return abort(make_response(jsonify(message="Missing payload"), 400))
    gcode_uuid = data.get("gcode", None)
    printer_uuid = data.get("printer",
                            None)  # FIXME: this should be part of the path
    if not gcode_uuid or not printer_uuid:
        return abort(
            make_response(
                jsonify(message="Missing gcode_uuid or printer_uuid"), 400))

    printer = printers.get_printer(printer_uuid)
    if not printer or printer['organization_uuid'] != org_uuid:
        raise http_exceptions.UnprocessableEntity(
            f"Invalid printer {printer_uuid} - does not exist.")

    gcode = gcodes.get_gcode(gcode_uuid)
    if not gcode:
        raise http_exceptions.UnprocessableEntity(
            "Invalid gcode {gcode_uuid} - does not exist.")

    network_client = network_clients.get_network_client(
        printer["network_client_uuid"])
    printer_data = dict(network_client)
    printer_data.update(dict(printer))
    printer_inst = clients.get_printer_instance(printer_data)
    try:
        printer_inst.upload_and_start_job(gcode["absolute_path"],
                                          gcode["path"])
    except DeviceInvalidState as e:
        raise http_exceptions.Conflict(*e.args)
    except DeviceCommunicationError as e:
        raise http_exceptions.GatewayTimeout(*e.args)
    # TODO: robin - add_printjob should be method of printer and printer a
    #               method of organization
    printjob_uuid = printjobs.add_printjob(
        gcode_uuid=gcode["uuid"],
        organization_uuid=org_uuid,
        printer_uuid=printer["uuid"],
        user_uuid=get_current_user()["uuid"],
        gcode_data={
            "uuid": gcode["uuid"],
            "filename": gcode["filename"],
            "size": gcode["size"],
            "available": True,
        },
        # FIXME: printer data should be kept in printer object only
        printer_data={
            "ip": printer_inst.ip,
            "port": printer_inst.port,
            "hostname": printer_inst.hostname,
            "name": printer_inst.name,
            "client": printer_inst.client,
        },
    )
    return (
        jsonify({
            "uuid": printjob_uuid,
            "user_uuid": get_current_user()["uuid"]
        }),
        201,
    )
Example #25
0
def printer_patch(uuid):
    try:
        uuidmodule.UUID(uuid, version=4)
    except ValueError:
        return abort(make_response("", 400))
    printer = printers.get_printer(uuid)
    if printer is None:
        return abort(make_response("", 404))
    data = request.json
    if not data:
        return abort(make_response("", 400))
    name = data.get("name", printer["name"])
    protocol = data.get("protocol", printer["protocol"])
    api_key = data.get("api_key", printer["client_props"].get("api_key", None))
    printer_props = data.get("printer_props", {})

    # TODO it might be necessary to update ip, hostname, port as well eventually
    if not name or protocol not in ["http", "https"]:
        return abort(make_response("", 400))
    printer_inst = clients.get_printer_instance(printer)
    printer_inst.add_api_key(api_key)
    if data.get("api_key", "-1") != "-1" and data.get(
            "api_key", "-1") != printer["client_props"].get("api_key", None):
        printer_inst.sniff(
        )  # this can probably be offloaded to check_printer task
    if printer_props:
        if not printer_inst.get_printer_props():
            printer_inst.printer_props = {}
        # This is effectively the only place where printer_props "validation" happens
        printer_inst.get_printer_props().update({
            k: printer_props[k]
            for k in [
                "filament_type",
                "filament_color",
                "bed_type",
                "tool0_diameter",
                "note",
            ] if k in printer_props
        })
    printers.update_printer(
        uuid=printer_inst.uuid,
        name=name,
        hostname=printer_inst.hostname,
        ip=printer_inst.ip,
        port=printer_inst.port,
        protocol=protocol,
        client=printer_inst.client_name(),
        client_props={
            "version": printer_inst.client_info.version,
            "connected": printer_inst.client_info.connected,
            "access_level": printer_inst.client_info.access_level,
            "api_key": printer_inst.client_info.api_key,
            "webcam": printer_inst.webcam(),
        },
        printer_props=printer_inst.get_printer_props(),
    )
    # TODO cache webcam, job, status for a small amount of time in client
    return (
        jsonify(
            make_printer_response(printer_inst, ["status", "webcam", "job"])),
        200,
    )
Example #26
0
def printjob_create(org_uuid):
    data = request.json
    if not data:
        return abort(make_response(jsonify(message="Missing payload"), 400))
    gcode_uuid = data.get("gcode", None)
    printer_uuid = data.get("printer", None)
    if not gcode_uuid or not printer_uuid:
        return abort(
            make_response(jsonify(message="Missing gcode_uuid or printer_uuid"), 400)
        )
    validate_uuid(gcode_uuid)
    validate_uuid(printer_uuid)
    printer = printers.get_printer(printer_uuid)
    if printer is None or printer["organization_uuid"] != org_uuid:
        return abort(make_response(jsonify(message="Not found"), 404))
    gcode = gcodes.get_gcode(gcode_uuid)
    if gcode is None:
        return abort(make_response(jsonify(message="Not found"), 404))
    try:
        network_client = network_clients.get_network_client(
            printer["network_client_uuid"]
        )
        printer_data = dict(network_client)
        printer_data.update(dict(printer))
        printer_inst = clients.get_printer_instance(printer_data)
        uploaded = printer_inst.upload_and_start_job(
            gcode["absolute_path"], gcode["path"]
        )
        if not uploaded:
            return abort(
                make_response(
                    jsonify(message="Cannot upload the g-code to the printer"), 500
                )
            )
        printjob_uuid = guid.uuid4()
        printjobs.add_printjob(
            uuid=printjob_uuid,
            gcode_uuid=gcode["uuid"],
            organization_uuid=org_uuid,
            printer_uuid=printer["uuid"],
            user_uuid=get_current_user()["uuid"],
            gcode_data={
                "uuid": gcode["uuid"],
                "filename": gcode["filename"],
                "size": gcode["size"],
                "available": True,
            },
            printer_data={
                "ip": printer_inst.ip,
                "port": printer_inst.port,
                "hostname": printer_inst.hostname,
                "name": printer_inst.name,
                "client": printer_inst.client,
            },
        )
        return (
            jsonify({"uuid": printjob_uuid, "user_uuid": get_current_user()["uuid"]}),
            201,
        )
    except clients.utils.PrinterClientException as e:
        app.logger.error(e)
        return abort(
            make_response(
                jsonify(message="Cannot schedule a printjob: %s" % str(e)), 409
            )
        )