at 25.11-pre 4.5 kB view raw
1# Test printing via CUPS. 2{ 3 pkgs, 4 socket ? true, # whether to use socket activation 5 listenTcp ? true, # whether to open port 631 on client 6 ... 7}: 8 9let 10 inherit (pkgs) lib; 11in 12 13{ 14 name = "printing"; 15 meta = with lib.maintainers; { 16 maintainers = [ 17 domenkozar 18 matthewbauer 19 ]; 20 }; 21 22 nodes.server = 23 { ... }: 24 { 25 services.printing = { 26 enable = true; 27 stateless = true; 28 startWhenNeeded = socket; 29 listenAddresses = [ "*:631" ]; 30 defaultShared = true; 31 openFirewall = true; 32 extraConf = '' 33 <Location /> 34 Order allow,deny 35 Allow from all 36 </Location> 37 ''; 38 }; 39 # Add a HP Deskjet printer connected via USB to the server. 40 hardware.printers.ensurePrinters = [ 41 { 42 name = "DeskjetLocal"; 43 deviceUri = "usb://foobar/printers/foobar"; 44 model = "drv:///sample.drv/deskjet.ppd"; 45 } 46 ]; 47 }; 48 49 nodes.client = 50 { lib, ... }: 51 { 52 services.printing.enable = true; 53 services.printing.startWhenNeeded = socket; 54 services.printing.listenAddresses = lib.mkIf (!listenTcp) [ ]; 55 # Add printer to the client as well, via IPP. 56 hardware.printers.ensurePrinters = [ 57 { 58 name = "DeskjetRemote"; 59 deviceUri = "ipp://server/printers/DeskjetLocal"; 60 model = "drv:///sample.drv/deskjet.ppd"; 61 } 62 ]; 63 hardware.printers.ensureDefaultPrinter = "DeskjetRemote"; 64 }; 65 66 testScript = '' 67 import os 68 import re 69 70 start_all() 71 72 with subtest("Make sure that cups is up on both sides and printers are set up"): 73 server.wait_for_unit("ensure-printers.service") 74 client.wait_for_unit("ensure-printers.service") 75 76 assert "scheduler is running" in client.succeed("lpstat -r") 77 78 with subtest("UNIX socket is used for connections"): 79 assert "/var/run/cups/cups.sock" in client.succeed("lpstat -H") 80 81 with subtest("HTTP server is available too"): 82 ${lib.optionalString listenTcp ''client.succeed("curl --fail http://localhost:631/")''} 83 client.succeed(f"curl --fail http://{server.name}:631/") 84 server.fail(f"curl --fail --connect-timeout 2 http://{client.name}:631/") 85 86 with subtest("LP status checks"): 87 assert "DeskjetRemote accepting requests" in client.succeed("lpstat -a") 88 assert "DeskjetLocal accepting requests" in client.succeed( 89 f"lpstat -h {server.name}:631 -a" 90 ) 91 client.succeed("cupsdisable DeskjetRemote") 92 out = client.succeed("lpq") 93 print(out) 94 assert re.search( 95 "DeskjetRemote is not ready.*no entries", 96 client.succeed("lpq"), 97 flags=re.DOTALL, 98 ) 99 client.succeed("cupsenable DeskjetRemote") 100 assert re.match( 101 "DeskjetRemote is ready.*no entries", client.succeed("lpq"), flags=re.DOTALL 102 ) 103 104 # Test printing various file types. 105 for file in [ 106 "${pkgs.groff.doc}/share/doc/*/examples/mom/penguin.pdf", 107 "${pkgs.groff.doc}/share/doc/*/meref.ps", 108 "${pkgs.cups.out}/share/doc/cups/images/cups.png", 109 "${pkgs.pcre.doc}/share/doc/pcre/pcre.txt", 110 ]: 111 file_name = os.path.basename(file) 112 with subtest(f"print {file_name}"): 113 # Print the file on the client. 114 print(client.succeed("lpq")) 115 client.succeed(f"lp {file}") 116 client.wait_until_succeeds( 117 f"lpq; lpq | grep -q -E 'active.*root.*{file_name}'" 118 ) 119 120 # Ensure that a raw PCL file appeared in the server's queue 121 # (showing that the right filters have been applied). Of 122 # course, since there is no actual USB printer attached, the 123 # file will stay in the queue forever. 124 server.wait_for_file("/var/spool/cups/d*-001") 125 server.wait_until_succeeds(f"lpq -a | grep -q -E '{file_name}'") 126 127 # Delete the job on the client. It should disappear on the 128 # server as well. 129 client.succeed("lprm") 130 client.wait_until_succeeds("lpq -a | grep -q -E 'no entries'") 131 132 retry(lambda _: "no entries" in server.succeed("lpq -a")) 133 134 # The queue is empty already, so this should be safe. 135 # Otherwise, pairs of "c*"-"d*-001" files might persist. 136 server.execute("rm /var/spool/cups/*") 137 ''; 138}