|
Lines 31-64
Link Here
|
| 31 |
# /usr/share/common-licenses/AGPL-3; if not, see |
31 |
# /usr/share/common-licenses/AGPL-3; if not, see |
| 32 |
# <http://www.gnu.org/licenses/>. |
32 |
# <http://www.gnu.org/licenses/>. |
| 33 |
|
33 |
|
| 34 |
import pprint |
34 |
import re |
| 35 |
import subprocess |
35 |
import subprocess |
| 36 |
import os |
36 |
import lxml.html |
| 37 |
import univention.management.console as umc |
|
|
| 38 |
import univention.management.console.modules as umcm |
| 39 |
from univention.management.console.modules import UMC_CommandError |
| 40 |
|
37 |
|
| 41 |
import univention.config_registry |
38 |
from univention.lib.i18n import Translation |
|
|
39 |
|
| 42 |
import univention.admin.uldap |
40 |
import univention.admin.uldap |
| 43 |
|
41 |
|
| 44 |
import re |
42 |
from univention.management.console.base import Base |
| 45 |
|
|
|
| 46 |
from univention.management.console.log import MODULE |
43 |
from univention.management.console.log import MODULE |
| 47 |
from univention.management.console.protocol.definitions import * |
44 |
from univention.management.console.config import ucr |
|
|
45 |
from univention.management.console.modules import UMC_Error |
| 48 |
from univention.management.console.modules.decorators import simple_response, log, sanitize |
46 |
from univention.management.console.modules.decorators import simple_response, log, sanitize |
| 49 |
from univention.management.console.modules.sanitizers import PatternSanitizer, ChoicesSanitizer |
47 |
from univention.management.console.modules.sanitizers import PatternSanitizer, ChoicesSanitizer |
| 50 |
|
48 |
|
| 51 |
_ = umc.Translation('univention-management-console-module-printers').translate |
49 |
_ = Translation('univention-management-console-module-printers').translate |
| 52 |
|
50 |
|
| 53 |
class Instance(umcm.Base): |
51 |
class Instance(Base): |
| 54 |
|
52 |
|
| 55 |
def init(self): |
53 |
def init(self): |
|
|
54 |
self._hostname = ucr.get('hostname') |
| 56 |
|
55 |
|
| 57 |
self.ucr = univention.config_registry.ConfigRegistry() |
|
|
| 58 |
self.ucr.load() |
| 59 |
|
| 60 |
self._hostname = self.ucr.get('hostname') |
| 61 |
|
| 62 |
@sanitize(pattern=PatternSanitizer(default='.*'), key=ChoicesSanitizer(choices=['printer', 'description', 'location'], required=True)) |
56 |
@sanitize(pattern=PatternSanitizer(default='.*'), key=ChoicesSanitizer(choices=['printer', 'description', 'location'], required=True)) |
| 63 |
@simple_response |
57 |
@simple_response |
| 64 |
def list_printers(self, key, pattern): |
58 |
def list_printers(self, key, pattern): |
|
Lines 105-147
Link Here
|
| 105 |
""" lists all quota entries related to this printer. """ |
99 |
""" lists all quota entries related to this printer. """ |
| 106 |
|
100 |
|
| 107 |
result = [] |
101 |
result = [] |
|
|
102 |
status = None |
| 108 |
|
103 |
|
| 109 |
if not os.path.exists('/usr/bin/pkusers'): |
104 |
try: |
| 110 |
raise UMC_CommandError(_('The print quota settings are currently disabled. Please install the package univention-printquota to enable them.')) |
105 |
from pykota.tool import PyKotaTool |
|
|
106 |
from pykota import reporter |
| 107 |
from pykota.storages.pgstorage import PGError |
| 108 |
except ImportError: |
| 109 |
raise UMC_Error(_('The print quota settings are currently disabled. Please install the package univention-printquota to enable them.')) |
| 111 |
|
110 |
|
| 112 |
(stdout, stderr, status) = self._shell_command(['/usr/bin/pkusers', '--list'], {'LANG':'C'}) |
111 |
reportTool = PyKotaTool() |
| 113 |
users = [] |
112 |
try: |
| 114 |
expr = re.compile('^\s*(.*?)\s+\-\s\<') |
113 |
reportTool.deferredInit() |
| 115 |
if status == 0: |
114 |
printers = reportTool.storage.getMatchingPrinters(printer) |
| 116 |
for line in stdout.split("\n"): |
115 |
reportingtool = reporter.openReporter(reportTool, 'html', printers, '*', 0) |
| 117 |
match = expr.match(line) |
116 |
status = reportingtool.generateReport() |
| 118 |
if match: |
117 |
except PGError as exc: |
| 119 |
users.append(match.group(1)) |
118 |
MODULE.error('Cannot connect to postgres: %s' % (exc,)) |
|
|
119 |
raise UMC_Error(_('The connection to the print quota postgres database failed. Please make sure the postgres service is running and reachable.')) |
| 120 |
finally: |
| 121 |
reportTool.regainPriv() |
| 120 |
|
122 |
|
| 121 |
result = [] |
123 |
if status: |
| 122 |
for user in users: |
124 |
tree = lxml.html.fromstring(status) |
| 123 |
if not os.path.exists('/usr/bin/repykota'): |
125 |
table = tree.find_class('pykotatable') |
| 124 |
raise UMC_CommandError(_('The print quota settings are currently disabled. Please install the package univention-printquota to enable them.')) |
126 |
for i in table: |
|
|
127 |
for a in i.iterchildren(tag='tr'): |
| 128 |
data = list() |
| 129 |
for b in a.iterchildren(tag='td'): |
| 130 |
data.append(b.text_content().strip()) |
| 131 |
if data and len(data) >= 11: |
| 132 |
user = data[0] |
| 133 |
#limitby = data[1] |
| 134 |
#overcharge = data[2] |
| 135 |
used = data[3] |
| 136 |
soft = data[4] |
| 137 |
hard = data[5] |
| 138 |
#balance = data[6] |
| 139 |
#grace = data[7] |
| 140 |
total = data[8] |
| 141 |
#paid = data[9] |
| 142 |
#warn = data[10] |
| 143 |
result.append(dict( |
| 144 |
user=user, |
| 145 |
used=used, |
| 146 |
soft=soft, |
| 147 |
hard=hard, |
| 148 |
total=total, |
| 149 |
)) |
| 125 |
|
150 |
|
| 126 |
(stdout, stderr, status) = self._shell_command(['/usr/bin/repykota', '-P', printer, user], {'LANG':'C'}) |
|
|
| 127 |
if status == 0: |
| 128 |
for line in stdout.split("\n"): |
| 129 |
data = line[16:].split() # ignore possibly truncated user name |
| 130 |
if len(data) >= 7: |
| 131 |
ok = True |
| 132 |
for n in (2, 3,4, len(data)-3): |
| 133 |
if not data[n].isdigit(): |
| 134 |
ok = False |
| 135 |
if ok: |
| 136 |
MODULE.info(" -> user='%s' used=%s soft=%s hard=%s total=%s" % (user, data[2], data[3], data[4], data[len(data)-3])) |
| 137 |
entry = { |
| 138 |
'user': user, |
| 139 |
'used': data[2], |
| 140 |
'soft': data[3], |
| 141 |
'hard': data[4], |
| 142 |
'total': data[len(data)-3] |
| 143 |
} |
| 144 |
result.append(entry) |
| 145 |
return result |
151 |
return result |
| 146 |
|
152 |
|
| 147 |
@simple_response |
153 |
@simple_response |
|
Lines 179-185
Link Here
|
| 179 |
|
185 |
|
| 180 |
return self._cancel_jobs(printer, jobs) |
186 |
return self._cancel_jobs(printer, jobs) |
| 181 |
|
187 |
|
| 182 |
|
|
|
| 183 |
@simple_response |
188 |
@simple_response |
| 184 |
@log |
189 |
@log |
| 185 |
def set_quota(self, printer='', user='', soft=0, hard=0): |
190 |
def set_quota(self, printer='', user='', soft=0, hard=0): |
|
Lines 324-330
Link Here
|
| 324 |
cmd.append(user) |
329 |
cmd.append(user) |
| 325 |
(stdout, stderr, status) = self._shell_command(cmd, {'LANG':'C'}) |
330 |
(stdout, stderr, status) = self._shell_command(cmd, {'LANG':'C'}) |
| 326 |
|
331 |
|
| 327 |
if status or len(stderr): |
332 |
if status or stderr: |
| 328 |
return stderr |
333 |
return stderr |
| 329 |
|
334 |
|
| 330 |
return '' |
335 |
return '' |
|
Lines 350-358
Link Here
|
| 350 |
return result |
355 |
return result |
| 351 |
|
356 |
|
| 352 |
# Printer specified: return its quota value or False if not found. |
357 |
# Printer specified: return its quota value or False if not found. |
| 353 |
if printer in result: |
358 |
return result.get(printer, False) |
| 354 |
return result[printer] |
|
|
| 355 |
return False |
| 356 |
|
359 |
|
| 357 |
def _cancel_jobs(self, printer, jobs): |
360 |
def _cancel_jobs(self, printer, jobs): |
| 358 |
""" internal function that cancels a list of jobs. |
361 |
""" internal function that cancels a list of jobs. |
|
Lines 375-378
Link Here
|
| 375 |
outputs = proc.communicate() |
378 |
outputs = proc.communicate() |
| 376 |
|
379 |
|
| 377 |
return (outputs[0], outputs[1], proc.returncode) |
380 |
return (outputs[0], outputs[1], proc.returncode) |
| 378 |
|
|
|