Ejemplo n.º 1
0
	def invoke_docker(self, function, app, force, values, progress):
		for setting in app.get_settings():
			if isinstance(setting, FileSetting) and not isinstance(setting, PasswordFileSetting):
				if values.get(setting.name):
					values[setting.name] = values[setting.name].decode('base64')
		progress.title = _('%s: Running tests') % app.name
		serious_problems = False
		if function == 'upgrade':
			_original_app = app
			app = Apps().find_candidate(app)
		if app is None:
			# Bug #44384: Under mysterious circumstances, app may be None after the .find_candidate()
			# This may happen in global App Center when the system the user is logged in has different ini files
			# than the system the App shall be upgraded on. E.g., in mixed appcenter / appcenter-test environments
			app = _original_app
			errors, warnings = {'must_have_candidate': False}, {}
		else:
			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:
			kwargs = {'noninteractive': True, 'skip_checks': ['shall_have_enough_ram', 'shall_only_be_installed_in_ad_env_with_password_service', 'must_not_have_concurrent_operation'], 'set_vars': values}
			if function == 'install':
				progress.title = _('Installing %s') % (app.name,)
			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
Ejemplo n.º 2
0
	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
Ejemplo n.º 3
0
	def invoke(self, request):
		# ATTENTION!!!!!!!
		# this function has to stay compatible with the very first App Center installations (Dec 2012)
		# if you add new arguments that change the behavior
		# you should add a new method (see invoke_dry_run) or add a function name (e.g. install-schema)
		# this is necessary because newer app center may talk remotely with older one
		#   that does not understand new arguments and behaves the old way (in case of
		#   dry_run: install application although they were asked to dry_run)
		host = request.options.get('host')
		function = request.options.get('function')
		send_as = function
		if function.startswith('install'):
			function = 'install'
		if function.startswith('update'):
			function = 'upgrade'
		if function == 'uninstall':
			function = 'remove'

		app_id = request.options.get('application')
		app = Apps().find(app_id)
		if app is None:
			raise umcm.UMC_Error(_('Could not find an application for %s') % (app_id,))
		force = request.options.get('force')
		values = request.options.get('values')
		only_dry_run = request.options.get('only_dry_run')
		dont_remote_install = request.options.get('dont_remote_install')
		only_master_packages = send_as.endswith('schema')
		MODULE.process('Try to %s (%s) %s on %s. Force? %r. Only master packages? %r. Prevent installation on other systems? %r. Only dry run? %r.' % (function, send_as, app_id, host, force, only_master_packages, dont_remote_install, only_dry_run))

		# REMOTE invocation!
		if host and host != self.ucr.get('hostname'):
			try:
				client = Client(host, self.username, self.password)
				result = client.umc_command('appcenter/invoke', request.options).result
			except (ConnectionError, HTTPError) as exc:
				MODULE.error('Error during remote appcenter/invoke: %s' % (exc,))
				result = {
					'unreachable': [host],
					'master_unreachable': True,
					'serious_problems': True,
					'software_changes_computed': True,  # not really...
				}
			else:
				if result['can_continue']:
					def _thread_remote(_client):
						with self.is_working():
							self._query_remote_progress(_client)

					def _finished_remote(thread, result):
						if isinstance(result, BaseException):
							MODULE.warn('Exception during %s %s: %s' % (function, app_id, str(result)))
					thread = notifier.threads.Simple('invoke', notifier.Callback(_thread_remote, client), _finished_remote)
					thread.run()
			self.finished(request.id, result)
			return

		# make sure that the application can be installed/updated
		action = get_action(function)()
		args = action._build_namespace(app=app, username=self.username, password=self.password, noninteractive=True, skip_checks=['shall_have_enough_ram', 'shall_only_be_installed_in_ad_env_with_password_service', 'must_not_have_concurrent_operation'], send_info=not only_master_packages, set_vars=values, dry_run=True, install_master_packages_remotely=False, only_master_packages=only_master_packages)

		can_continue = True
		delayed_can_continue = True
		serious_problems = False
		result = {
			'install': [],
			'remove': [],
			'broken': [],
			'unreachable': [],
			'master_unreachable': False,
			'serious_problems': False,
			'hosts_info': {},
			'problems_with_hosts': False,
			'serious_problems_with_hosts': False,
			'invokation_forbidden_details': {},
			'invokation_warning_details': {},
			'software_changes_computed': False,
		}
		if not app:
			MODULE.process('Application not found: %s' % app_id)
			can_continue = False
		if can_continue and not only_master_packages:
			if function == 'upgrade':
				app = Apps().find_candidate(app)
			if app is None:
				forbidden, warnings = {'must_have_candidate': False}, {}
			else:
				forbidden, warnings = app.check(function)
			if forbidden:
				MODULE.process('Cannot %s %s: %r' % (function, app_id, forbidden))
				result['invokation_forbidden_details'] = forbidden
				can_continue = False
				serious_problems = True
			if warnings:
				MODULE.process('Warning trying to %s %s: %r' % (function, app_id, forbidden))
				result['invokation_warning_details'] = warnings
				if not force:
					# don't stop "immediately".
					#   compute the package changes!
					delayed_can_continue = False
		result['serious_problems'] = serious_problems
		result['can_continue'] = can_continue
		if can_continue:
			with self.locked():
				if can_continue and function in ('install', 'upgrade'):
					result.update(self._install_dry_run_remote(app, function, dont_remote_install, force))
					serious_problems = bool(result['master_unreachable'] or result['serious_problems_with_hosts'])
					if serious_problems:
						args.dry_run = True
					result.update(action.dry_run(app, args))
					result['software_changes_computed'] = True
					serious_problems = bool(result['broken'] or serious_problems)
					if serious_problems or (not force and (result['unreachable'] or result['install'] or result['remove'] or result['problems_with_hosts'])):
						can_continue = False
				elif can_continue and function in ('remove',) and not force:
					result.update(action.dry_run(app, args))
					result['software_changes_computed'] = True
					can_continue = False
				can_continue = can_continue and delayed_can_continue and not only_dry_run
				result['serious_problems'] = serious_problems
				result['can_continue'] = can_continue

				if can_continue and not only_dry_run:
					def _thread(module, app, function):
						with module.is_working():
							if not dont_remote_install and function != 'remove':
								self._install_master_packages_on_hosts(app, function)
							with module.package_manager.no_umc_restart(exclude_apache=True):
								try:
									args.dry_run = False
									args.install_master_packages_remotely = False
									return action.call_with_namespace(args)
								except AppCenterError as exc:
									raise umcm.UMC_Error(str(exc), result=dict(
										display_feedback=True,
										title='%s %s' % (exc.title, exc.info)))
					def _finished(thread, result):
						if isinstance(result, BaseException):
							MODULE.warn('Exception during %s %s: %s' % (function, app_id, str(result)))
					thread = notifier.threads.Simple('invoke', notifier.Callback(_thread, self, app, function), _finished)
					thread.run()
		self.finished(request.id, result)