def _sanitize(self, value, name, further_args): app = Apps.find_by_string(value) if not app: self.raise_validation_error(_("Could not find an application for %s") % (value, )) app_version = app.version if not app.is_installed() and not app.install_permissions_exist(): apps = Apps().get_all_apps_with_id(app.id) apps = [_app for _app in apps if not _app.install_permissions] if apps: for _app in apps: if _app.version == app_version: app = _app break else: app = sorted(apps)[-1] return app
def _install_master_packages(self, app, unregister_if_uninstalled=False): old_app = Apps().find(app.id) was_installed = old_app.is_installed() if self._register_component(app): update_packages() ret = self._install_packages(app.default_packages_master) if was_installed: if old_app != app: self.log('Re-registering component for %s' % old_app) if self._register_component(old_app): update_packages() elif unregister_if_uninstalled: self.log('Unregistering component for %s' % app) if self._unregister_component(app): update_packages() return ret
def main(self, args): apps = args.app real_apps = [] for app in apps: _apps = Apps().get_all_apps_with_id(app.id) if app._docker_prudence_is_true(): _apps = [_app for _app in _apps if not _app.docker] if _apps: app = sorted(_apps)[-1] self.warn( 'Using %s instead of %s because docker is to be ignored' % (app, args.app)) else: raise InstallNonDockerVersionError(args.app) if not app.install_permissions_exist(): _apps = [ _app for _app in _apps if not _app.install_permissions ] if _apps: app = sorted(_apps)[-1] self.warn( 'Using %s instead of %s because of lacking install permissions' % (app, args.app)) else: raise InstallWithoutPermissionError() real_apps.append(app) args.app = real_apps return self.do_it(args)
def _list(self, pattern): ret = [] for app in self.get_apps(): versions = [] installations = {} if pattern: if not fnmatch(app.id, pattern): continue app = Apps().find(app.id, latest=True) for _app in Apps().get_all_apps_with_id(app.id): ldap_obj = get_app_ldap_object(_app) servers = ldap_obj.installed_on_servers() versions.append(_app.version) installations[_app.version] = servers ret.append((app, versions, installations)) return ret
def test_upgrade(self, app): if app.required_app_version_upgrade: required_version = LooseVersion(app.required_app_version_upgrade) installed_app = Apps().find(app.id) installed_version = LooseVersion(installed_app.version) if required_version > installed_version: return {'required_version': app.required_app_version_upgrade}
def _get_docker(cls, app): if not app.docker: return if app.plugin_of: app = Apps().find(app.plugin_of) return cls._get_docker(app) return Docker(app, cls.logger)
def main(self, args): if not args.apps: args.apps = Apps().get_all_locally_installed_apps() self.logfile_logger = get_logfile_logger('update-certificates') for app in args.apps: self.log('updating certificates for {0}'.format(app)) self.update_certificates(app)
def get_apps(no_cache=False): if no_cache: AppCache().clear_cache() get = get_action('get') return [ get.to_dict(app) for app in Apps().get_all_apps() if app.is_ucs_component() ]
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('.*([0-9]+\.[0-9]+).*', '\\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 _sanitize(self, value, name, further_args): app_id = value app_version = None if '=' in value: app_id, app_version = tuple(value.split('=', 1)) app = Apps().find(app_id, app_version=app_version) if not app.is_installed() and not app.install_permissions_exist(): apps = Apps().get_all_apps_with_id(app.id) apps = [_app for _app in apps if not _app.install_permissions] if apps: if app_version: for _app in apps: if _app.version == app_version: app = _app break else: app = sorted(apps)[-1] return app
def app_is_running(app): from univention.appcenter.app_cache import Apps if isinstance(app, basestring): app = Apps().find(app) if app: if not app.docker: return False if not app.is_installed(): return False try: from univention.appcenter.docker import Docker except ImportError: return None else: docker = Docker(app) return docker.is_running() else: return None
def _install_master_packages(self, app, percentage_end=100, unregister_if_uninstalled=False): old_app = Apps().find(app.id) was_installed = old_app.is_installed() self._register_component(app) ret = self._install_packages(app.default_packages_master, percentage_end) if was_installed: if old_app != app: self.log('Re-registering component for %s' % old_app) self._register_component(old_app) self._apt_get_update() elif unregister_if_uninstalled: self.log('Unregistering component for %s' % app) self._unregister_component(app) self._apt_get_update() return ret
def invoke_docker(self, function, app, force, values, progress): if function == 'upgrade': app = Apps().find_candidate(app) serious_problems = False progress.title = _('%s: Running tests') % (app.name,) errors, warnings = app.check(function) can_continue = force # "dry_run" if errors: MODULE.process('Cannot %s %s: %r' % (function, app.id, errors)) serious_problems = True can_continue = False if warnings: MODULE.process('Warning trying to %s %s: %r' % (function, app.id, warnings)) result = { 'serious_problems': serious_problems, 'invokation_forbidden_details': errors, 'invokation_warning_details': warnings, 'can_continue': can_continue, 'software_changes_computed': False, } if can_continue: with self.locked(): kwargs = {'noninteractive': True, 'skip_checks': ['shall_have_enough_ram', 'shall_only_be_installed_in_ad_env_with_password_service', 'must_not_have_concurrent_operation']} if function == 'install': progress.title = _('Installing %s') % (app.name,) kwargs['set_vars'] = values elif function == 'uninstall': progress.title = _('Uninstalling %s') % (app.name,) elif function == 'upgrade': progress.title = _('Upgrading %s') % (app.name,) action = get_action(function) handler = UMCProgressHandler(progress) handler.setLevel(logging.INFO) action.logger.addHandler(handler) try: result['success'] = action.call(app=app, username=self.username, password=self.password, **kwargs) except AppCenterError as exc: raise umcm.UMC_Error(str(exc), result=dict( display_feedback=True, title='%s %s' % (exc.title, exc.info))) finally: action.logger.removeHandler(handler) return result
def _register_installed_apps_in_ucr(self): installed_codes = [] for app in Apps().get_all_apps(): if app.is_installed(): installed_codes.append(app.code) with catch_stdout(self.logger): ucr_save({ 'appcenter/installed': '-'.join(installed_codes), 'repository/app_center/installed': '-'.join(installed_codes), # to be deprecated })
def _upgrade_docker(self, app, args): install = get_action('install')() action_args = install._build_namespace(_namespace=args, app=app, set_vars=self._get_configure_settings(self.old_app, filter_action=False), send_info=False, skip_checks=['must_not_be_installed']) if install.call_with_namespace(action_args): app_cache = Apps() for _app in app_cache.get_all_apps(): if _app.plugin_of == app.id and _app.is_installed(): _app = app_cache.find(_app.id, latest=True) if _app.docker: _old_app = self.old_app self._upgrade_docker(_app, args) self.old_app = _old_app remove = get_action('remove')() action_args = remove._build_namespace(_namespace=args, app=self.old_app, send_info=False, skip_checks=['must_not_be_depended_on']) remove._remove_app(self.old_app, action_args) if remove._unregister_component(self.old_app): update_packages() self._call_join_script(app, args) # run again in case remove() called an installed unjoin script self.old_app = app
def _candidate_dict(cls, app): ret = {} if app.is_installed(): candidate = Apps().find_candidate(app) else: candidate = None if candidate: ret['update_available'] = True ret['candidate_docker'] = candidate.docker ret['candidate_version'] = candidate.version ret['candidate_component_id'] = candidate.component_id ret['candidate_readme_update'] = candidate.readme_update ret['candidate_readme_post_update'] = candidate.readme_post_update ret['candidate_needs_install_permissions'] = not candidate.install_permissions_exist() ret['candidate_install_permissions_message'] = candidate.install_permissions_message else: ret['update_available'] = False # TODO: ucr.is_true(app.ucr_upgrade_key); Bug#39916 ret['candidate_needs_install_permissions'] = not app.install_permissions_exist() ret['candidate_install_permissions_message'] = app.install_permissions_message return ret
def get_default_values(app): from univention.appcenter.ini_parser import IniSectionAttribute from univention.appcenter.settings import BoolSetting, FileSetting, IntSetting, ListSetting, PasswordFileSetting, PasswordSetting, StatusSetting, StringSetting, UDMListSetting for kls in [ StringSetting, IntSetting, BoolSetting, ListSetting, UDMListSetting, FileSetting, PasswordFileSetting, PasswordSetting, StatusSetting ]: if 'default_for_testing' not in kls._attrs: attr = IniSectionAttribute() attr.name = 'default_for_testing' kls._attrs['default_for_testing'] = attr app = FindApps().find(app) app = FindApps().find_candidate(app) or app ret = {} for setting in app.get_settings(): value = setting.default_for_testing if value is not None: ret[setting.name] = setting.sanitize_value(app, value) return ret
def test_upgrade(self, apps): current_ram = get_current_ram_available() required_ram = 0 for app in apps: required_ram += app.min_physical_ram installed_app = Apps().find(app.id) # is already installed, just a minor version upgrade # RAM "used" by this installed app should count # as free. best approach: subtract it required_ram -= installed_app.min_physical_ram if current_ram < required_ram: return {'minimum': required_ram, 'current': current_ram}
def _appcenter_caches(self, args): if args.appcenter_server: return [AppCenterCache(server=args.appcenter_server)] else: ret = [] servers = set() for appcenter_cache in Apps().get_appcenter_caches(): server = appcenter_cache.get_server() if server not in servers: servers.add(server) ret.append(appcenter_cache) return ret
def get_blocking_apps(cls, ucs_version): ''' checks if update is possible for this app ''' ucs_version = UCS_Version(ucs_version + '-0') next_minor = '%(major)d.%(minor)d' % ucs_version next_version = '%(major)d.%(minor)d-%(patchlevel)d' % ucs_version current_version = UCS_Version(ucr_get('version/version') + '-0') current_minor = '%(major)d.%(minor)d' % current_version # if this is just a patchlevel update, everything is fine if current_minor >= next_minor: return {} # first, update the local cache and get current apps update = get_action('update') update.logger = get_logfile_logger('update-check') update.call() current_cache = Apps(locale='en') # get apps in next version with TemporaryDirectory() as tempdir: update.call(ucs_version=next_minor, cache_dir=tempdir, just_get_cache=True) next_cache = AppCenterCache.build(ucs_versions=next_minor, server=default_server(), locale='en', cache_dir=tempdir) next_apps = next_cache.get_every_single_app() # check apps blocking_apps = dict() for app in current_cache.get_all_locally_installed_apps(): if not cls.app_can_update(app, next_version, next_apps): cls.debug('app %s is not available for %s' % (app.id, next_version)) blocking_apps[app.component_id] = app.name else: cls.debug('app %s is available for %s' % (app.id, next_version)) return blocking_apps
def _update_apps(self, args): self.log( 'Updating all installed Apps to use the new App Center server') logfile_logger = get_logfile_logger('dev-use-test-appcenter') for app in Apps().get_all_locally_installed_apps(): self.log('Updating %s' % app) register = get_action('register') # we should only use ['component'] in container_mode() # and None otherwise, because it is more correct. however, # this would require credentials (for potential schema updates etc) register.call(apps=[app], register_task=['component']) if app.docker and not container_mode(): try: from univention.appcenter.docker import Docker except ImportError: # should not happen self.log('univention-appcenter-docker is not installed') continue start = get_action('start') start.call(app=app) docker = Docker(app, self.logger) self.log('Updating container... (checking for appbox)') if docker.execute('which', 'univention-app').returncode == 0: self.log( '... setting the new App Center inside the container') returncode = docker.execute( 'univention-install', '-y', 'univention-appcenter-dev', _logger=logfile_logger).returncode if returncode != 0: self.warn( 'univention-install univention-appcenter-dev failed!' ) if args.revert: returncode = docker.execute( 'univention-app', 'dev-use-test-appcenter', '--revert', _logger=logfile_logger).returncode else: returncode = docker.execute( 'univention-app', 'dev-use-test-appcenter', '--appcenter-host', args.appcenter_host, _logger=logfile_logger).returncode if returncode != 0: self.fatal( 'univention-app dev-use-test-appcenter failed!') else: self.log('... nothing to do here')
def main(self, args): reload_package_manager() apps = args.apps if not apps: self.debug('No apps given. Using all') apps = Apps().get_all_apps() self._register_component_for_apps(apps, args) self._register_files_for_apps(apps, args) self._register_host_for_apps(apps, args) self._register_app_for_apps(apps, args) self._register_database_for_apps(apps, args) self._register_attributes_for_apps(apps, args) self._register_installed_apps_in_ucr()
def _candidate_dict(cls, app): ret = {} candidate = Apps().find_candidate(app) if candidate: ret['update_available'] = True ret['candidate_docker'] = candidate.docker ret['candidate_version'] = candidate.version ret['candidate_component_id'] = candidate.component_id ret['candidate_readme_update'] = candidate.readme_update ret['candidate_readme_post_update'] = candidate.readme_post_update else: ret['update_available'] = False # TODO: ucr.is_true(app.ucr_upgrade_key); Bug#39916 return ret
def _install_packages_dry_run(self, app, args, with_dist_upgrade): original_app = Apps().find(app.id) if original_app.is_installed(): was_installed = True else: was_installed = False self.log('Dry run for %s' % app) if self._register_component(app): self.debug('Updating packages') update_packages() self.debug('Component %s registered' % app.component_id) pkgs = self._get_packages_for_dry_run(app, args) self.debug('Dry running with %r' % pkgs) ret = install_packages_dry_run(pkgs) if with_dist_upgrade: upgrade_ret = dist_upgrade_dry_run() ret['install'] = sorted( set(ret['install']).union(set(upgrade_ret['install']))) ret['remove'] = sorted( set(ret['remove']).union(set(upgrade_ret['remove']))) ret['broken'] = sorted( set(ret['broken']).union(set(upgrade_ret['broken']))) if args.install_master_packages_remotely: # TODO: should test remotely self.log('Not testing package changes of remote packages!') pass if args.dry_run or ret['broken']: if was_installed: if self._register_component(original_app): self.debug('Updating packages') update_packages() self.debug('Component %s reregistered' % original_app.component_id) else: if self._unregister_component(app): self.debug('Updating packages') update_packages() self.debug('Component %s unregistered' % app.component_id) return ret
def buy(self, application): app = Apps().find(application) if not app or not app.shop_url: return None ret = {} ret['key_id'] = self.ucr.get('license/uuid') ret['ucs_version'] = self.ucr.get('version/version') ret['app_id'] = app.id ret['app_version'] = app.version # ret['locale'] = locale.getlocale()[0] # done by frontend ret['user_count'] = None # FIXME: get users and computers from license ret['computer_count'] = None return ret
def test_install(self, app): conflictedapps = set() apps_cache = Apps() # check ConflictedApps for _app in apps_cache.get_all_apps(): if not _app._allowed_on_local_server(): # cannot be installed, continue continue if _app.id in app.conflicted_apps or app.id in _app.conflicted_apps: if _app.is_installed(): conflictedapps.add(_app.id) elif _app in self.other_apps(app): conflictedapps.add(_app.id) # check port conflicts ports = [] for i in app.ports_exclusive: ports.append(i) for i in app.ports_redirection: ports.append(i.split(':', 1)[0]) for app_id, container_port, host_port in app_ports(): if app_id != app.id and str(host_port) in ports: conflictedapps.add(app_id) for _app in self.other_apps(app): other_ports = set() for i in _app.ports_exclusive: other_ports.add(i) for i in _app.ports_redirection: other_ports.add(i.split(':', 1)[0]) if other_ports.intersection(ports): conflictedapps.add(_app.id) if conflictedapps: conflictedapps = [ apps_cache.find(app_id) for app_id in conflictedapps ] return [{ 'id': _app.id, 'name': _app.name } for _app in conflictedapps if _app]
def test_install(self, app): unmet_apps = [] apps_cache = Apps() # RequiredApps for _app in apps_cache.get_all_apps(): if _app.id in app.required_apps: if not _app.is_installed(): unmet_apps.append({ 'id': _app.id, 'name': _app.name, 'in_domain': False }) # RequiredAppsInDomain domain = get_action('domain') apps = [ apps_cache.find(app_id) for app_id in app.required_apps_in_domain ] apps_info = domain.to_dict(apps) for _app in apps_info: if not _app: continue if not _app['is_installed_anywhere']: local_allowed = _app['id'] not in app.conflicted_apps unmet_apps.append({ 'id': _app['id'], 'name': _app['name'], 'in_domain': True, 'local_allowed': local_allowed }) unmet_apps = [ unmet_app for unmet_app in unmet_apps if unmet_app['id'] not in (_app.id for _app in self.other_apps(app)) ] if unmet_apps: return unmet_apps
def test_remove(self, app): depending_apps = [] apps_cache = Apps() # RequiredApps for _app in apps_cache.get_all_apps(): if app.id in _app.required_apps and _app.is_installed(): depending_apps.append({'id': _app.id, 'name': _app.name}) # RequiredAppsInDomain apps = [ _app for _app in apps_cache.get_all_apps() if app.id in _app.required_apps_in_domain ] if apps: domain = get_action('domain') self_info = domain.to_dict([app])[0] hostname = ucr_get('hostname') if not any( inst['version'] for host, inst in self_info['installations'].iteritems() if host != hostname): # this is the only installation apps_info = domain.to_dict(apps) for _app in apps_info: if _app['is_installed_anywhere']: depending_apps.append({ 'id': _app['id'], 'name': _app['name'] }) depending_apps = [ depending_app for depending_app in depending_apps if depending_app['id'] not in (_app.id for _app in self.other_apps(app)) ] if depending_apps: return depending_apps
def _get_app_network(self): _logger.debug('Getting network for %s' % self.app) network = ucr_get(self.app.ucr_ip_key) if network and '/' in network: _logger.debug('Found %s' % network) try: network = IPv4Network(u'%s' % (network, ), False) except ValueError as exc: _logger.warn('Error using the network %s: %s' % (network, exc)) return None else: return network docker0_net = IPv4Network( u'%s' % (ucr_get('appcenter/docker/compose/network', '172.16.1.1/16'), ), False) gateway, netmask = docker0_net.exploded.split('/', 1) # '172.16.1.1', '16' used_docker_networks = [] for _app in Apps().get_all_apps( ): # TODO: find container not managed by the App Center? if _app.id == self.app.id: continue ip = ucr_get(_app.ucr_ip_key) try: app_network = IPv4Network(u'%s' % (ip, ), False) except ValueError as exc: continue else: used_docker_networks.append(app_network) prefixlen_diff = 24 - int(netmask) if prefixlen_diff <= 0: _logger.warn( 'Cannot get a subnet big enough' ) # maybe I could... but currently, I only work with 24-netmasks return None for network in docker0_net.subnets( prefixlen_diff ): # 172.16.1.1/24, 172.16.2.1/24, ..., 172.16.255.1/24 _logger.debug('Testing %s' % network) if IPv4Address(u'%s' % (gateway, )) in network: _logger.debug('Refusing due to "main subnet"') continue if any( app_network.overlaps(network) for app_network in used_docker_networks): _logger.debug('Refusing due to range already used') continue return network _logger.warn('Cannot find any viable subnet')
def get_requested_apps(): ret = [] try: with open(APPCENTER_FILE) as f: for line in f: app = Apps().find(line.strip()) if app: ret.append(app) else: pass #utils.fail('Error finding %s' % (line,)) except EnvironmentError: pass #utils.fail('Error reading %s: %s' % (APPCENTER_FILE, exc)) return ret