Source code for univention.appcenter.actions.domain

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Univention App Center
#  univention-app module for managing apps in the domain
#
# Copyright 2015-2022 Univention GmbH
#
# https://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <https://www.gnu.org/licenses/>.
#

import re

from univention.appcenter.log import LogCatcher
from univention.appcenter.utils import call_process, get_local_fqdn
from univention.appcenter.udm import search_objects
from univention.appcenter.app_cache import Apps
from univention.appcenter.actions.credentials import CredentialsAction
from univention.appcenter.actions import get_action
from univention.appcenter.ucr import ucr_get, ucr_is_false


[docs]class Domain(CredentialsAction): '''Shows information about the domain and enabled management of app installations.''' help = 'Domain management'
[docs] def setup_parser(self, parser): pass
[docs] def main(self, args): lo, pos = self._get_ldap_connection(args, allow_machine_connection=True) first = True localhost = ucr_get('hostname') username = '%s$@%%s' % localhost pwdfile = '/etc/machine.secret' for obj in self.get_appcenter_hosts(lo, pos): if not first: self.log('') fqdn = obj.info.get('fqdn') self.log('%s:' % fqdn) logger = LogCatcher() output = self.manage(username % fqdn, pwdfile, logger, 'info') if output.has_stdout(): for line in output.stdout(): self.log(line) else: self.warn('Failed to get info') if output.has_stderr(): for line in output.stderr(): self.warn(line) first = False
[docs] def get_appcenter_hosts(self, lo, pos): ret = [] for role in ['domaincontroller_master', 'domaincontroller_backup', 'domaincontroller_slave', 'memberserver']: objs = search_objects('computers/%s' % role, lo, pos) for obj in objs: if 'serverRole' not in obj.info: continue if 'docker' in obj.info.get('objectFlag', []): continue ret.append(obj) return ret
[docs] def manage(self, login, pwdfile, logger, *args): process_args = ['/usr/sbin/univention-ssh', pwdfile, login, 'univention-app'] + list(args) call_process(process_args, logger=logger) return logger
[docs] @classmethod def to_dict(cls, apps): self = cls() lo, pos = self._get_ldap_connection(args=None, allow_machine_connection=True) hosts = self.get_appcenter_hosts(lo, pos) if ucr_is_false('appcenter/domainwide'): hostname = ucr_get('hostname') hosts = [host for host in hosts if host['name'] == hostname] get = get_action('get') ret = [] app_ldap_objects = search_objects('appcenter/app', lo, pos) for app in apps: if not app: ret.append(None) else: app_dict = get.to_dict(app) app_dict['installations'] = self._get_installations(app, hosts, app_ldap_objects) app_dict['is_installed_anywhere'] = any(inst['version'] for inst in app_dict['installations'].values()) app_dict['fully_loaded'] = True ret.append(app_dict) return ret
def _get_installations(self, app, hosts, app_ldap_objects): ret = {} local_ucs_version = ucr_get('version/version') for host in hosts: candidate = self._find_latest_app_version(app) role = host.info.get('serverRole')[0] description = host.info.get('description') remote_ucs_version = host.info.get('operatingSystemVersion') is_local = host.info.get('fqdn') == get_local_fqdn() if remote_ucs_version: remote_ucs_version = re.sub(r'.*([0-9]+\.[0-9]+).*', r'\1', remote_ucs_version) ip = host.info.get('ip') # list version = None update_available = None for app_obj in app_ldap_objects: app_obj_version = app_obj.info.get('version') app_obj_id = app_obj.info.get('id')[:-len(app_obj_version) - 1] if app_obj_id == app.id: if host.info.get('fqdn') in app_obj.info.get('server', []): version = app_obj_version break if local_ucs_version != remote_ucs_version: # unable to compute directly... better treat as not available update_available = False elif version: remote_app = Apps().find(app.id, app_version=version) if remote_app: prevent_docker = None if not is_local: prevent_docker = True candidate = Apps().find_candidate(remote_app, prevent_docker=prevent_docker) or remote_app update_available = remote_app < candidate ret[host['name']] = { 'ucs_version': remote_ucs_version, 'version': version, 'update_available': update_available, 'candidate_version': candidate.version, 'description': description, 'ip': ip, 'role': role, } return ret def _find_latest_app_version(self, app): candidate = Apps().find_candidate(app) return candidate or app