c0c0n3 / odoo.box

All of Martel's Odoo stack on just one NixOS machine.
MIT License
2 stars 0 forks source link

wkhtmltopdf woes #23

Open c0c0n3 opened 3 months ago

c0c0n3 commented 3 months ago

At the moment Odoo can call wkhtmltopdf to generate timesheet reports, timesheet data gets output correctly in the PDF but the Martel template doesn't get applied so the report looks dull.

Also there's some potential issues with the wkhtmltopdf versions we use. The one we had in K8s is an x86 binary compiled with wkhtmltopdf's own patched Qt lib (https://github.com/wkhtmltopdf/wkhtmltopdf) as reported by the tool

$ kubectl -n martel exec -it odoo-community-6f47c5586-47fth -- sh
$ wkhtmltopdf --version
wkhtmltopdf 0.12.6.1 (with patched qt)

Notice there's no official 0.12.6.1 version, so this must be a patched Debian thingie. Also notice the Odoo guys say you shouldn't be using that version with Odoo 14 which actually requires version 0.12.5:

This is why we build that version for Odoo box. Our build works both for x86 and ARM64 architectures but it links an external Qt lib instead of compiling in the one the wkhtmltopdf guys patched. Now they say you should use either the patched or unpatched version depending on your use case since some features available in the unpatched version aren't available in the patched one and vice-versa. It looks like we need the patched version though. In fact, when tryna print a PDF from a timesheet, we get this error message in the Odoo logs:

... wkhtmltopdf: The switch --header-spacing, is not support using unpatched qt ...

which is probably why the PDF contains all the timesheet data but without the formatting in the Martel template.

We've also tried using an x86 binary on an x86 machine. This binary contains a patched version and so wkhtmltopdf doesn't moan about unsupported features anymore---i.e. the above message is gone from the Odoo logs. But still the Martel template doesn't get applied to the PDF, the error message in the Odoo logs now is

odoo.addons.base.models.ir_actions_report:
wkhtmltopdf: Exit with code 1 due to network error: ContentNotFoundError

So it looks like we've made some progress and now it could be just a matter of Odoo not passing in the template file when calling wkhtmltopdf or wkhtmltopdf not being able to access that file.

Bless this mess!

c0c0n3 commented 3 months ago

for the record, here's the Odoo log from the time we hit the button to generate a PDF from a timesheet until the PDF was downloaded.

debug.txt

c0c0n3 commented 3 months ago

also, these are the libs linked to the wkhtmltopdf we have in the K8s cluster.

$ kubectl -n martel exec -it odoo-community-6f47c5586-47fth -- sh
$ ldd $(which wkhtmltopdf)
    linux-vdso.so.1 (0x00007ffd00b63000)
    libjpeg.so.62 => /usr/lib/x86_64-linux-gnu/libjpeg.so.62 (0x00007f2489b15000)
    libpng16.so.16 => /usr/lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f2489adb000)
    libXrender.so.1 => /usr/lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f24898d1000)
    libfontconfig.so.1 => /usr/lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f248988b000)
    libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f24897c8000)
    libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f2489685000)
    libssl.so.1.1 => /usr/lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f24895f0000)
    libcrypto.so.1.1 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f24892fc000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f24892df000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f24892d9000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f24892b7000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f24890ea000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2488fa4000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f2488f8a000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2488db6000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f248c6d6000)
    libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f2488d87000)
    libuuid.so.1 => /usr/lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f2488d7e000)
    libbrotlidec.so.1 => /usr/lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007f2488d70000)
    libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f2488d43000)
    libbrotlicommon.so.1 => /usr/lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007f2488d20000)
    libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f2488d1b000)
    libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f2488b15000)
    libbsd.so.0 => /usr/lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f2488afe000)
    libmd.so.0 => /usr/lib/x86_64-linux-gnu/libmd.so.0 (0x00007f2488aef000)
c0c0n3 commented 3 months ago

If needed we could compile our own wkhtmltopdf 0.12.5-1 with their patched Qt by doing something similar to what they do here:

Basically, it boils down to converting their Docker build functions to Nix

But possibly a better option could be to piggyback on

marcothedood commented 3 months ago

Issue is fixed on the x86 machine

Basically the error string wkhtmltopdf: Exit with code 1 **due to network error: ContentNotFoundError** is due to an Odoo variable misconfiguration.

The odoo motherfckr has a system paramenter called web.base.url and Idk why it was set up by default on "https://odoo.martel-innovate.com".

To be able to see the system parameters you gotta have enabled the "developer tool". -- https://odoo.sucks/web?debug=assets,tests#action=8&model=ir.config_parameter&view_type=list&cids=&menu_id=4

You can access this variable from the application > settings > technical > system parameters

When printing the timesheet, Odoo was calling the stylesheet and the JS file from https://odoo.martel-innovate.com/web/wada-wada/web.report_assets_common.css and of course, because / thanks to the firewall we were getting the middle finger as response

Moreover, very likely odoo didn't even rewrite the url, imagine how it had been badly engineered. That's why even from the browser inspector nothing was displayed.

On this note, lucky me - I forked your repo and merged the x86 branch to the main one. Now I am cloning mine to the martel's org setting the repo as (private) so as to have the credentials pvt.

Then will create an AMI starting form the actual x86 machine and creating a new instance with lower specs starting from that image --> importing recent data and deliver it for testing.

Also keep in mind that, even after this tweak, the outputs were not the same:

  1. On the x86 machine using wkhtmltopdf 0.12.6-3 w/ qt patched the rendering was fine
  2. On the actual test-odoo.martel-innovate.com ARM using wkhtmltopdf 0.12.5, some components were broken (logo and bold chars)

Attached you can find the 2 samples.

Hell yeah!

Timesheets (11).pdf Timesheets (12).pdf

c0c0n3 commented 3 months ago

@m3dd3fx good catch, excellent work!!

It looks like this web.base.url is a total pain in the backside. Just try googling "odoo web.base.url". Here's one of the results which makes for an interesting reading, to say the least:

Tracing Odoo system calls in the dev VM

$ sudo strace -f -s 10000 -p 3994 -p 4064 -p 4065 -p 4069 -o dump.txt

confirms your analysis. Here's the params Odoo passes to wktmltopdf when printing a timesheet

--disable-local-file-access --cookie session_id 9788661b0f5a22ae8670d0d66df578c80d59f50c
--quiet
--page-size A4 --margin-top 40.0 --dpi 90 --zoom 1.0666666666666667
--header-spacing 35 --margin-left 7.0 --margin-bottom 32.0 --margin-right 7.0
--orientation Portrait
--javascript-delay 1000
--header-html /tmp/report.header.tmp.je3ozjx6.html
--footer-html /tmp/report.footer.tmp.44rnems3.html
 /tmp/report.body.tmp.0.pxvmtvd9.html
 /tmp/report.tmp.mt3x57ht.pdf     

The header, body and footer file args are temp HTML files Odoo writes before calling wkhtmltopdf, e.g. the header

openat(AT_FDCWD, "/tmp/report.header.tmp.je3ozjx6.html", ...
write(17, "\n        <!DOCTYPE html>\n        <base href=https://odoo.martel-innovate.com>\n   ...

which contains this HTML

<!DOCTYPE html>
<base href=https://odoo.martel-innovate.com>
<html style="height: 0;">
  <head>
    <link type="text/css=" rel="stylesheet" 
        href="/web/content/38829127-cd253c1/web.report_assets_pdf.css"
        data-asset-xmlid="web.report_assets_pdf" data-asset-version="cd253c1"/>
    <link type="text/css" rel="stylesheet" 
        href="/web/content/38829125-b64992f/web.report_assets_common.css"
        data-asset-xmlid="web.report_assets_common" data-asset-version="b64992f"/>

...

Notice the base URL set to the value of the web.base.url Odoo sys config param. The stylesheets are absolute paths which b/c of the base URL get resolved to https://odoo.martel-innovate.com/web/content/.... Likewise, the body and footer files also contain <base href=https://odoo.martel-innovate.com>.

Now in the dev VM we've got an unpatched wkhtmltopdf which ignores the header and footer args, among others

wkhtmltopdf:
The switch --header-spacing, is not support using unpatched qt, and will be ignored.
The switch --header-html, is not support using unpatched qt, and will be ignored.
The switch --footer-html, is not support using unpatched qt, and will be ignored.

But it does try to convert the HTML body file to PDF. In doing so, it connects to odoo.martel-innovate.com

connect(9, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("3.121.61.170")}, 16) = 0
$ dog odoo.martel-innovate.com
CNAME odoo.martel-innovate.com.                                                   5m00s   "ae9ff73d8d87e40b1b6945133012c365-2011518872.eu-central-1.elb.amazonaws.com."
    A ae9ff73d8d87e40b1b6945133012c365-2011518872.eu-central-1.elb.amazonaws.com. 1m00s   3.125.20.6
    A ae9ff73d8d87e40b1b6945133012c365-2011518872.eu-central-1.elb.amazonaws.com. 1m00s   3.121.61.170

to download the stylesheet files, but it fails

write(2, "Exit with code 1 due to network error: ContentNotFoundError\n", 60) = 60

most likely b/c these files have a different version tag---e.g. 38829125-b64992f.

Here's the whole trace:

dump.txt

c0c0n3 commented 3 months ago

So where does all that leave us? I think we should go live with the patched wktmltopdf which means we're forced to run on x86_64. Long term, we should build our patched wktmltopdf, as explained earlier.

marcothedood commented 3 months ago

I agree to go over with the x86 machine since we don't care about spending some cents more x hr. here u can find the detailed price x instance:

t3.medium (2cpu 4G Ram) - $0.0418 / hr t4g.medium (2cpu 4G Ram) - $0.0336 / hr

Our task now requires us to deploy a stable vers of odoo asap (probably Massimo wants to announce it @ the plenary in zh)