Source code for univention.management.console.modules.printers

#!/usr/bin/python3
#
# Univention Management Console
#  module: updater
#
# SPDX-FileCopyrightText: 2011-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only

import re
import subprocess

from univention.config_registry import ConfigRegistry
from univention.lib.i18n import Translation
from univention.management.console.base import Base
from univention.management.console.config import ucr
from univention.management.console.error import UMC_Error
from univention.management.console.modules.decorators import log, sanitize, simple_response
from univention.management.console.modules.sanitizers import ChoicesSanitizer, PatternSanitizer
from univention.udm import UDM


_ = Translation('univention-management-console-module-printers').translate


[docs] class Instance(Base):
[docs] @sanitize(pattern=PatternSanitizer(default='.*'), key=ChoicesSanitizer(choices=['printer', 'description', 'location'], required=True)) @simple_response def list_printers(self, key, pattern): """Lists the printers for the overview grid.""" result = [] plist = self._list_printers() for element in plist: printer = element['printer'] data = self._printer_details(printer) for field in data: element[field] = data[field] # filter according to query if pattern.match(element[key]): result.append(element) return result
[docs] @simple_response @log def get_printer(self, printer=''): """gets detail data for one printer.""" result = self._printer_details(printer) result['printer'] = printer result['status'] = self._printer_status(printer) return result
[docs] @simple_response def list_users(self): """ convenience function for the username entry. Lists all user names. We don't return this as an array of {id, label} tuples because: (1) id and label are always the same here (2) at the frontend, we must do some postprocessing, and an array is easier to handle. (3) the ComboBox is able to handle a plain array. """ ucr = ConfigRegistry() ucr.load() identity = ucr.get('ldap/hostdn') with open('/etc/machine.secret') as fd: password = fd.readline().strip() server = ucr.get('ldap/server/name') udm = UDM.credentials(identity, password, server=server).version(2) users = udm.get('users/user').search() return [user.props.username for user in users]
[docs] @simple_response def list_jobs(self, printer=''): """lists jobs for a given printer, directly suitable for the grid""" # NOTE: we don't set language to 'neutral' since it is useful # to get localized date/time strings. result = [] (stdout, _stderr, status) = self._shell_command(['/usr/bin/lpstat', '-o', printer]) expr = re.compile(r'\s*(\S+)\s+(\S+)\s+(\d+)\s*(.*?)$') if status == 0: for line in stdout.split("\n"): mobj = expr.match(line) if mobj: entry = { 'job': mobj.group(1), 'owner': mobj.group(2), 'size': int(mobj.group(3)), 'date': mobj.group(4), } result.append(entry) return result
def _list_printers(self): """returns a list of printers, along with their 'enabled' status.""" result = [] expr = re.compile(r'printer\s+(\S+)\s.*?(\S+abled)') (stdout, _stderr, status) = self._shell_command(['/usr/bin/lpstat', '-p'], {'LANG': 'C'}) if status == 0: for line in stdout.split("\n"): mobj = expr.match(line) if mobj: entry = {'printer': mobj.group(1), 'status': mobj.group(2)} result.append(entry) return result def _printer_status(self, printer): """returns the 'enabled' status of a printer""" (stdout, _stderr, status) = self._shell_command(['/usr/bin/lpstat', '-p', printer], {'LANG': 'C'}) if status == 0: if ' enabled ' in stdout: return 'enabled' if ' disabled ' in stdout: return 'disabled' return 'unknown' def _printer_details(self, printer): """returns as much as possible details about a printer.""" result = {} expr = re.compile(r'\s+([^\s\:]+)\:\s*(.*?)$') (stdout, _stderr, status) = self._shell_command(['/usr/bin/lpstat', '-l', '-p', printer], {'LANG': 'C'}) if status == 0: for line in stdout.split("\n"): mobj = expr.match(line) if mobj: result[mobj.group(1).lower()] = mobj.group(2) result['server'] = ucr.get('hostname') return result
[docs] @simple_response @log def enable_printer(self, printer='', on=False): """enable or disable a printer, depending on args.""" cmd = 'univention-cups-enable' if on else 'univention-cups-disable' (_stdout, stderr, status) = self._shell_command([cmd, printer]) if status: raise UMC_Error(_('Could not %s printer: %s') % (_('activate') if on else _('deactivate'), stderr))
[docs] @simple_response @log def cancel_jobs(self, jobs, printer=''): """ cancels one or more print jobs. Job IDs are passed as an array that can be directly passed on to the _shell_command() method """ args = ['/usr/bin/cancel', '-U', '%s$' % ucr.get('hostname')] for job in jobs: args.append(job) # noqa: PERF402 args.append(printer) (_stdout, stderr, status) = self._shell_command(args) if status: raise UMC_Error(_('Could not cancel job: %s') % (stderr,))
def _shell_command(self, args, env=None): proc = subprocess.Popen(args=args, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) stdout, stderr = proc.communicate() stdout, stderr = stdout.decode('UTF-8', 'replace'), stderr.decode('UTF-8', 'replace') return (stdout, stderr, proc.returncode)