Beispiel #1
0
 def partitions_info(self, request):
     result = {}
     message = None
     try:
         fs = fstab.File()
         mt = mtab.File()
     except IOError as error:
         MODULE.error("Could not open %s" % error.filename)
         message = _("Could not open %s") % error.filename
         request.status = MODULE_ERR
     else:
         partition = fs.find(spec=request.options["partitionDevice"])
         if partition:
             mounted_partition = mt.get(partition.spec)
             if mounted_partition:
                 result["mountPoint"] = mounted_partition.mount_point
                 result["filesystem"] = mounted_partition.type
                 result["options"] = mounted_partition.options
                 request.status = SUCCESS
             else:
                 request.status = MODULE_ERR
                 message = _("This partition is currently not mounted")
         else:
             request.status = MODULE_ERR
             message = _("No partition found")
     self.finished(request.id, result, message)
Beispiel #2
0
def getUserAndMailbox(userdn):
	co, lo, pos = getCoLoPos()

	server = univention.admin.modules.get("asterisk/server")
	univention.admin.modules.init(lo, pos, server)
	objs = server.lookup(co, lo, None)

	checkServers = []
	for obj in objs:
			checkServers.append({
				"label": obj["commonName"],
			})

	MODULE.error('User: server: %s' % len(checkServers))
	if len(checkServers) >0 :
		co, lo = getCoLo()

		user = getUser(co, lo, userdn)

		mailbox = user.get("mailbox")
		if mailbox:
			mailbox = getMailbox(co, lo, mailbox)

		return user, mailbox
	elif len(checkServers) == 0 :
		MODULE.error('Fehler gefunden!')
		mailbox = "KeinServer"
		user = "******"
		return user, mailbox
Beispiel #3
0
 def partitions_query(self, request):
     result = []
     message = None
     try:
         fs = fstab.File()
         mt = mtab.File()
     except IOError as error:
         MODULE.error("Could not open %s" % error.filename)
         message = _("Could not open %s") % error.filename
         request.status = MODULE_ERR
     else:
         partitions = fs.get(["xfs", "ext3", "ext2"], False)  # TODO: ext4?
         for partition in partitions:
             list_entry = {}
             list_entry["partitionDevice"] = partition.spec
             list_entry["mountPoint"] = partition.mount_point
             list_entry["partitionSize"] = None
             list_entry["freeSpace"] = None
             list_entry["inUse"] = None
             mounted_partition = mt.get(partition.spec)
             if mounted_partition:
                 partition_info = df.DeviceInfo(partition.mount_point)
                 list_entry["partitionSize"] = tools.block2byte(partition_info.size(), "GB", 1)
                 list_entry["freeSpace"] = tools.block2byte(partition_info.free(), "GB", 1)
                 if "usrquota" in mounted_partition.options:
                     list_entry["inUse"] = True
                 else:
                     list_entry["inUse"] = False
             result.append(list_entry)
         request.status = SUCCESS
     self.finished(request.id, result, message)
def get_fqdn(nameserver):
    # register nameserver
    resolver = _get_dns_resolver(nameserver)

    # perform a reverse lookup
    try:
        reverse_address = dns.reversename.from_address(nameserver)
        MODULE.info('Found reverse address: %s' % (reverse_address, ))
        reverse_lookup = resolver.query(reverse_address, 'PTR')
        if not len(reverse_lookup):
            return None

        fqdn = reverse_lookup[0]
        parts = [i for i in fqdn.target.labels if i]
        domain = '.'.join(parts)

        return domain
    except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer,
            dns.resolver.NoNameservers) as exc:
        MODULE.warn('Lookup for nameserver %s failed: %s %s' %
                    (nameserver, type(exc).__name__, exc))
    except dns.exception.Timeout as exc:
        MODULE.warn('Lookup for nameserver %s timed out: %s' %
                    (nameserver, exc))
    except dns.exception.DNSException as exc:
        MODULE.error('DNS Exception: %s' % (traceback.format_exc()))
    return None
Beispiel #5
0
    def updates_available(self, request):
        """ Asks if there are package updates available. (don't get confused
			by the name of the UniventionUpdater function that is called here.)
			This is a seperate call since it can take an amount of time, thus
			being invoked by a seperate button (and not in the background)
		"""
        # ----------- DEBUG -----------------
        MODULE.info("updater/updates/available invoked with:")
        pp = pprint.PrettyPrinter(indent=4)
        st = pp.pformat(request.options).split("\n")
        for s in st:
            MODULE.info("   << %s" % s)
            # -----------------------------------
        result = False
        what = "starting"
        try:
            # be as current as possible.
            what = "reinitializing UniventionUpdater"
            self.uu.ucr_reinit()
            what = "reloading registry"
            self.ucr.load()

            what = "checking update availability"
            result = self.uu.component_update_available()

        except Exception, ex:
            typ = str(type(ex)).strip("<>")
            msg = "[while %s] [%s] %s" % (what, typ, str(ex))
            # result['message'] = msg
            # result['status'] = 1
            MODULE.error(msg)
Beispiel #6
0
	def request( self, command, **kwargs ):
		MODULE.info( 'Sending request %s to UVMM daemon ...' % command )
		try:
			request = eval( 'protocol.Request_%s()' % command )
		except NameError, AttributeError:
			MODULE.error( 'Failed to create request %s' % command )
			raise UVMM_Error( _( 'The given UVMM command is not known' ) )
Beispiel #7
0
    def error_handling(self, request, method, etype, exc, etraceback):
        if self.__handler:
            self.__handler._Base__requests[request.id] = (request, method)
            self.__handler._Base__error_handling(request, method, etype, exc,
                                                 etraceback)
            return

        trace = ''.join(traceback.format_exception(etype, exc, etraceback))
        MODULE.error('The init function of the module failed\n%s: %s' % (
            exc,
            trace,
        ))
        from ..error import UMC_Error
        if not isinstance(exc, UMC_Error):
            error = _('The initialization of the module failed: %s') % (
                trace, )
            exc = UMC_Error(error, status=MODULE_ERR_INIT_FAILED)
            etype = UMC_Error

        resp = Response(request)
        resp.status = exc.status
        resp.message = str(exc)
        resp.result = exc.result
        resp.headers = exc.headers
        self.response(resp)
Beispiel #8
0
 def request(self, command, **kwargs):
     MODULE.info('Sending request %s to UVMM daemon ...' % command)
     try:
         request = eval('protocol.Request_%s()' % command)
     except NameError, AttributeError:
         MODULE.error('Failed to create request %s' % command)
         raise UVMM_Error(_('The given UVMM command is not known'))
Beispiel #9
0
		def _thread(request):
			message = None
			success = True
			result = []

			partition = request.options['partitionDevice']
			unicode_user = request.options['user']
			user = unicode_user.encode('utf-8')
			size_soft = request.options['sizeLimitSoft']
			size_hard = request.options['sizeLimitHard']
			file_soft = request.options['fileLimitSoft']
			file_hard = request.options['fileLimitHard']
			self._check_error(request, partition)
			failed = tools.setquota(partition, user, tools.byte2block(size_soft),
			                        tools.byte2block(size_hard),
			                        file_soft, file_hard)
			if failed:
				MODULE.error('Failed to modify quota settings for user %s '
				             'on partition %s' % (user, partition))
				message = _('Failed to modify quota settings for user %s on '
				            'partition %s') % (user, partition)
				request.status = MODULE_ERR
				self.finished(request.id, None, message)
			message = _('Successfully set quota settings')
			return {'result': result, 'message': message, 'success': success}
Beispiel #10
0
        def _thread(request):
            message = None
            success = True
            result = []

            partition = request.options['partitionDevice']
            unicode_user = request.options['user']
            user = unicode_user.encode('utf-8')
            size_soft = request.options['sizeLimitSoft']
            size_hard = request.options['sizeLimitHard']
            file_soft = request.options['fileLimitSoft']
            file_hard = request.options['fileLimitHard']
            self._check_error(request, partition)
            failed = tools.setquota(partition, user,
                                    tools.byte2block(size_soft),
                                    tools.byte2block(size_hard), file_soft,
                                    file_hard)
            if failed:
                MODULE.error('Failed to modify quota settings for user %s '
                             'on partition %s' % (user, partition))
                message = _('Failed to modify quota settings for user %s on '
                            'partition %s') % (user, partition)
                request.status = MODULE_ERR
                self.finished(request.id, None, message)
            message = _('Successfully set quota settings')
            return {'result': result, 'message': message, 'success': success}
Beispiel #11
0
 def startDemoServer(self, allowed_clients=[]):
     if not self.connected():
         MODULE.error('%s: not connected - skipping startDemoServer' %
                      (self.ipAddress, ))
         return
     self._core.stopDemoServer()
     self._core.startDemoServer(ITALC_VNC_PORT, ITALC_DEMO_PORT)
     self.allowClients(allowed_clients)
Beispiel #12
0
 def denyClients(self):
     if not self.connected():
         MODULE.error('%s: not connected - skipping denyClients' %
                      (self.ipAddress, ))
         return
     for client in self._allowedClients[:]:
         self._core.demoServerUnallowHost(client.ipAddress)
         self._allowedClients.remove(client)
Beispiel #13
0
 def ucr_try_int(variable, default):
     try:
         return int(ucr.get(variable, default))
     except ValueError:
         MODULE.error(
             'UCR variables %s is not a number, using default: %s' %
             (variable, default))
         return default
Beispiel #14
0
 def startDemoClient(self, server, fullscreen=True):
     if not self.connected():
         MODULE.error('%s: not connected - skipping startDemoClient' %
                      (self.ipAddress, ))
         return
     self._core.stopDemo()
     self._core.unlockScreen()
     self._core.unlockInput()
     self._core.startDemo(server.ipAddress, ITALC_DEMO_PORT, fullscreen)
Beispiel #15
0
 def allowClients(self, clients):
     if not self.connected():
         MODULE.error('%s: not connected - skipping allowClients' %
                      (self.ipAddress, ))
         return
     self.denyClients()
     for client in clients:
         self._core.demoServerAllowHost(client.ipAddress)
         self._allowedClients.append(client)
Beispiel #16
0
 def load(self):
     for plugin in self.plugins:
         try:
             self.modules[plugin] = Plugin(plugin)
         except ImportError as exc:
             MODULE.error('Could not load plugin %r: %r' % (plugin, exc))
             raise
     self.modules = OrderedDict(
         sorted(self.modules.items(), key=lambda t: t[0]))
def getServer(dn):
	co, lo, pos = getCoLoPos()
	server = univention.admin.modules.get("asterisk/server")
	univention.admin.modules.init(lo, pos, server)
	obj = server.object(co, lo, None, dn)
	MODULE.error("server dn: %s" % dn)
	obj.open()

	return obj
Beispiel #18
0
 def powerOn(self):
     # do not use the italc trick
     # if self._core and self.macAddress:
     # 	self._core.powerOnComputer( self.macAddress )
     if self.macAddress:
         subprocess.Popen(['/usr/bin/wakeonlan', self.macAddress])
     else:
         MODULE.error('%s: no MAC address set - skipping powerOn' %
                      (self.ipAddress, ))
Beispiel #19
0
	def connect(self):
		# Create a connection to the pkgdb
		try:
			self.dbConnection = updb.open_database_connection(self.ucr, pkgdbu=True)
		except pgdb.InternalError as ex:
			MODULE.error('Could not establish connection to the PostgreSQL server: %s' % (ex,))
			raise UMC_Error(_('Could not establish connection to the database.\n\n%s') % (_server_not_running_msg(),))
		else:
			self.cursor = self.dbConnection.cursor()
Beispiel #20
0
 def lockInput(self, value):
     if not self.connected():
         MODULE.error('%s: not connected - skipping lockInput' %
                      (self.ipAddress, ))
         return
     if value:
         self._core.lockInput()
     else:
         self._core.unlockInput()
Beispiel #21
0
 def get(self, request):
     """get a specific item of self.data"""
     try:
         item = self.data[request.options['item']]
     except IndexError:
         MODULE.error('A invalid item was accessed.')
         raise UMC_Error(_('The item %d does not exists.') %
                         (request.options['item'], ),
                         status=400)
     self.finished(request.id, self.data[item])
 def init(self):
     MODULE.info("Initializing 'updater' module (PID = %d)" % (getpid(), ))
     self._current_job = ''
     self._logfile_start_line = 0
     self._serial_file = Watched_File(COMPONENTS_SERIAL_FILE)
     self._updates_serial = Watched_Files(UPDATE_SERIAL_FILES)
     try:
         self.uu = UniventionUpdater(False)
     except Exception as exc:  # FIXME: let it raise
         MODULE.error("init() ERROR: %s" % (exc, ))
def check_domain_is_higher_or_equal_version(address, username, password):
	with _temporary_password_file(password) as password_file:
		try:
			master_ucs_version = subprocess.check_output(['univention-ssh', password_file, '%s@%s' % (username, address), 'echo $(/usr/sbin/ucr get version/version)-$(/usr/sbin/ucr get version/patchlevel)'], stderr=subprocess.STDOUT).rstrip()
		except subprocess.CalledProcessError:
			MODULE.error('Failed to retrieve UCS version: %s' % (traceback.format_exc()))
			return
		nonmaster_ucs_version = '{}-{}'.format(UCR.get('version/version'), UCR.get('version/patchlevel'))
		if LooseVersion(nonmaster_ucs_version) > LooseVersion(master_ucs_version):
			raise UMC_Error(_('The UCS version of the domain you are trying to join ({}) is lower than the local one ({}). This constellation is not supported.').format(master_ucs_version, nonmaster_ucs_version))
		def _thread(request, obj):
			# acquire the lock until the scripts have been executed
			self._finishedResult = False
			obj._finishedLock.acquire()
			try:
				subfolders = {
					'network': ['30_net'],
					'certificate': ['40_ssl'],
					'languages': ['15_keyboard', '20_language', '35_timezone'],
				}.get(request.flavor)

				self._progressParser.reset(subfolders)

				if request.flavor == 'setup':
					# adjust progress fractions for setup wizard with pre-configurred settings
					fractions = self._progressParser.fractions
					fractions['05_role/10role'] = 0
					fractions['10_basis/12domainname'] = 0
					fractions['10_basis/14ldap_basis'] = 0
					fractions['90_postjoin/10admember'] = 0
					self._progressParser.calculateFractions()

				MODULE.info('saving profile values')
				util.write_profile(values)

				if not values:
					MODULE.error('No property "values" given for save().')
					return False

				# in case of changes of the IP address, restart UMC server and web server
				# for this we ignore changes of virtual or non-default devices
				# ... no need to restart the UMC server if cleanup scripts are run anyway
				restart = False
				if not run_hooks:
					MODULE.info('Check whether ip addresses have been changed')
					for ikey, ival in values.iteritems():
						if RE_IPV4.match(ikey) or RE_IPV6_DEFAULT.match(ikey) or RE_SSL.match(ikey):
							restart = True
							break
					MODULE.info('Restart servers: %s' % restart)

				# on a joined system or on a basesystem, we can run the setup scripts
				MODULE.info('runnning system setup scripts (flavor %r)' % (request.flavor,))

				util.run_scripts(self._progressParser, restart, subfolders, lang=str(self.locale), args=script_args)

				# run cleanup scripts and appliance hooks if needed
				if run_hooks:
					util.cleanup(with_appliance_hooks=True)

				# done :)
				self._finishedResult = True
				return True
			finally:
				obj._finishedLock.release()
Beispiel #25
0
    def groups_add(self, request):
        if not type(request.options) == list:
            raise UMC_OptionTypeError(
                _('Options have to be given as list of dictionarys.'))

        messages = []
        for group in request.options:
            options = None
            groupname = None
            users = None
            command = ['/usr/sbin/groupadd']
            exit_code = None

            try:
                if not type(group) == dict:
                    raise ValueError(_('Invalid optiontype.'))
                options = group.get('object', {})
                if not type(options) == dict:
                    raise ValueError(_('Invalid optiontype.'))

                groupname = options.get('groupname')
                users = options.get('users')

                if not groupname is not None:
                    raise ValueError(_('Groupname is required.'))
                if not type(groupname) == str:
                    raise ValueError(_('Groupname has to be given as string.'))
                self.validate_name(groupname)
                command += [groupname]

                # execute "groupadd"
                exit_code = self.process(command)
                if exit_code == 9:
                    raise ValueError(
                        _('Groupname "%s" is already in use.') % groupname)
                if exit_code:
                    MODULE.error('Processing "%s" failed and returned %s' %
                                 (str(command), str(exit_code)))
                    raise CreatingError(
                        _('Could not create group. See log for more information.'
                          ))
                if users is not None:
                    if not type(users) == list:
                        raise ModifyError(_('Users have to be given as list.'))
                    if self.process(
                        ['/usr/bin/gpasswd', '-M', ','.join(users),
                         groupname]):
                        raise ModifyError(_('Could not set list of users.'))
            except (ValueError, CreatingError, ModifyError) as e:
                messages += [str(e)]
                if type(e) == ModifyError:
                    self.process(['/usr/sbin/groupdel', groupname])
            else:
                messages += ['']
        self.finished(request.id, messages)
Beispiel #26
0
    def _createProjectDir(self):
        '''Create project directory in the senders home.'''
        if not self.sender:
            return

        self._create_project_dir(self.sender, self.sender_projectdir)

        if not self.sender_projectdir:
            MODULE.error(
                'ERROR: Sender information is not specified, cannot create project dir in the sender\'s home!'
            )
    def rules_get(self, iterator):
        """Returns the specified rules

		requests.options = [
			<string>,
		]
		"""
        def get_address_type(address):
            if backend.REGEX_RULE_ADDRESS.match(address):
                return address
            else:
                return u'specific'

        def get_address_value(address):
            if backend.REGEX_RULE_ADDRESS.match(address):
                return None
            else:
                return address

        # Try to load firewall configuration
        try:
            firewall = backend.Firewall()
        except backend.Error as e:
            message = _(u"Could not load firewall configuration")
            MODULE.error(u"%s: %s" % (
                message,
                str(e),
            ))
            raise umc.modules.UMC_CommandError(message)

        for identifier in iterator:
            try:
                rule = firewall.rules[identifier]

                entry = {
                    u'identifier': rule.identifier,
                    u'protocol': rule.protocol,
                    u'portStart': rule.port[0],
                    u'portEnd': (rule.port[1] - 1),
                    u'addressType': get_address_type(rule.address),
                    u'addressValue': get_address_value(rule.address),
                    u'packageName': rule.package,
                    u'action': rule.action.lower(),
                    u'description': self._get_description(rule.description),
                }
            except (backend.Error, KeyError) as e:
                message = _(u"Could not get firewall rule")
                MODULE.error(u"%s: %s" % (
                    message,
                    str(e),
                ))
                raise umc.modules.UMC_CommandError(message)
            else:
                yield entry
Beispiel #28
0
	def test_connection(self):
		# test if connection is still active
		try:
			self.cursor.execute('SELECT TRUE')
		except pgdb.OperationalError as ex:
			MODULE.error('Connection to the PostgreSQL server lost: %s' % (ex,))
			self.dbConnection = None
			try:
				self.connect()
			except UMC_Error:
				raise UMC_Error(_('Connection to the dabase lost.\n\n%s') % (_server_not_running_msg(),))
Beispiel #29
0
	def _thread_finished(self, thread, thread_result, request):
		if not isinstance(thread_result, BaseException):
			request.status = SUCCESS
			self.finished(request.id, {'objects': thread_result['result'],
			                           'success': thread_result['success']},
			              thread_result['message'])
		else:
			message = str(thread_result) + '\n' + '\n'.join(thread.trace)
			MODULE.error('An internal error occurred: %s' % message)
			request.status = MODULE_ERR
			self.finished(request.id, None, message)
Beispiel #30
0
	def lang_timezones(self, request):
		'''Return a list of all available time zones.'''
		try:
			file = open('/lib/univention-installer/locale/timezone')
		except:
			MODULE.error( 'Cannot find locale data for timezones in /lib/univention-installer/locale' )
			self.finished(request.id, None)
			return

		timezones = [ i.strip('\n') for i in file if not i.startswith('#') ]

		self.finished(request.id, timezones)
    def init(self):
        os.umask(
            0o022
        )  # umc umask is too restrictive for app center as it creates a lot of files in docker containers
        self.ucr = ucr_instance()

        self.update_applications_done = False
        install_opener(self.ucr)
        self._is_working = False

        try:
            self.package_manager = PackageManager(
                info_handler=MODULE.process,
                step_handler=None,
                error_handler=MODULE.warn,
                lock=False,
            )
        except SystemError as exc:
            MODULE.error(str(exc))
            raise umcm.UMC_Error(str(exc), status=500)
        self.package_manager.set_finished(
        )  # currently not working. accepting new tasks
        get_package_manager._package_manager = self.package_manager

        # build cache
        _update_modules()
        get_action('list').get_apps()

        # not initialize here: error prone due to network errors and also kinda slow
        self._uu = None
        self._cm = None

        # in order to set the correct locale
        locale.setlocale(locale.LC_ALL, str(self.locale))

        try:
            log_to_logfile()
        except IOError:
            pass

        # connect univention.appcenter.log to the progress-method
        handler = ProgressInfoHandler(self.package_manager)
        handler.setLevel(logging.INFO)
        get_base_logger().addHandler(handler)

        percentage = ProgressPercentageHandler(self.package_manager)
        percentage.setLevel(logging.DEBUG)
        get_base_logger().getChild('actions.install.progress').addHandler(
            percentage)
        get_base_logger().getChild('actions.upgrade.progress').addHandler(
            percentage)
        get_base_logger().getChild('actions.remove.progress').addHandler(
            percentage)
Beispiel #32
0
 def _createCacheDir(self):
     '''Create cache directory.'''
     # create project cache directory
     MODULE.info('creating project cache dir: %s' % self.cachedir)
     try:
         os.makedirs(self.cachedir, 0o700)
         os.chown(self.cachedir, 0, 0)
     except (OSError, IOError) as exc:
         if exc.errno == errno.EEXIST:
             MODULE.info('cache dir %s exists.' % self.cachedir)
         else:
             MODULE.error('Failed to create cachedir: %s' % (exc, ))
Beispiel #33
0
def cleanup():
    # write header before executing scripts
    f = open(LOG_FILE, 'a')
    f.write('\n\n=== Cleanup (%s) ===\n\n' % timestamp())
    f.flush()

    ucr = univention.config_registry.ConfigRegistry()
    ucr.load()

    # The browser was only started, if system/setup/boot/start is true
    if ucr.is_true('system/setup/boot/start', False):
        MODULE.info('Appliance mode: try to shut down the browser')
        try:
            fpid = open(PATH_BROWSER_PID)
            strpid = fpid.readline().strip()
            pid = int(strpid)
            p = psutil.Process(pid)
            p.kill()
        except IOError:
            MODULE.warn('cannot open browser PID file: %s' % PATH_BROWSER_PID)
        except ValueError:
            MODULE.error('browser PID is not a number: "%s"' % strpid)
        except psutil.NoSuchProcess:
            MODULE.error('cannot kill process with PID: %s' % pid)

        # Maybe the system-setup CMD tool was started
        for p in psutil.process_iter():
            if p.name == 'python2.6' and '/usr/share/univention-system-setup/univention-system-setup' in p.cmdline:
                p.kill()

    # unset the temporary interface if set
    for var in ucr.keys():
        if RE_IPV4_TYPE.match(var) and ucr.get(
                var) == 'appliance-mode-temporary':
            f.write('unset %s' % var)
            keys = [var]
            for k in ['netmask', 'address', 'broadcast', 'network']:
                keys.append(var.replace('/type', '/%s' % k))
            univention.config_registry.handler_unset(keys)
            # Shut down temporary interface
            subprocess.call(
                ['ifconfig',
                 var.split('/')[1].replace('_', ':'), 'down'])

    # force a restart of UMC servers and apache
    subprocess.call(CMD_DISABLE_EXEC, stdout=f, stderr=f)
    subprocess.call(CMD_ENABLE_EXEC_WITH_RESTART, stdout=f, stderr=f)

    f.write('\n=== DONE (%s) ===\n\n' % timestamp())
    f.flush()
    f.close()

    return True
	def lang_timezones(self, request):
		'''Return a list of all available time zones.'''
		try:
			file = open('/usr/share/univention-system-setup/locale/timezone')
		except EnvironmentError:
			MODULE.error('Cannot find locale data for timezones in /usr/share/univention-system-setup/locale')
			self.finished(request.id, None)
			return

		timezones = [i.strip('\n') for i in file if not i.startswith('#')]

		self.finished(request.id, timezones)
Beispiel #35
0
	def _get_all(self, klass, school, filter_str, lo):
		if school:
			schools = [School.cache(school)]
		else:
			schools = School.from_binddn(lo)
		objs = []
		for school in schools:
			try:
				objs.extend(klass.get_all(lo, school.name, filter_str=filter_str, easy_filter=True))
			except noObject as exc:
				MODULE.error('Could not get all objects of %r: %r' % (klass.__name__, exc))
		return [obj.to_dict() for obj in objs]
Beispiel #36
0
	def users_put(self, object):
		"""
			modify a local user
		"""

		response = []
		errors = {
			# no information about returncodes, yet
		}

		try:
			success = True
			message = ''

			# Username
			username = object.get('$username$')
			new_username = object.get('username')

			pwoptions = {}
			cmd = ['/usr/sbin/usermod']
			cmd += self._get_common_args( object, pwoptions )

			# Change username
			if username != new_username:
				cmd += ['-l', new_username]

			# Account deactivation
			if pwoptions.get('lock'):
				cmd.append('-L')

			elif object.get('unlock'):
				cmd.append('-U')

			# Password
			password = object.get('password')
			self._change_user_password(username, password, pwoptions)

			# Execute
			if len(cmd) > 1:
				cmd.append(username)
				returncode = self.process(cmd)
				if returncode != 0:
					MODULE.error("cmd '%s' failed with returncode %d" % (' '.join(map(str, cmd)) returncode))
					error = errors.get( returncode, _('unknown error with statuscode %d occurred') % (returncode) )
					raise ValueError( error )

		except ValueError as e:
			success = False
			message = '%s%s' % ('%s: ' % username if isinstance(username, basestring) else '', e,)

		MODULE.info( 'luga.users_edit: results: %s' % (message,) )
		return {'message': message, 'success': success}
Beispiel #37
0
	def users_add(self, object):
		"""
			add a local user
		"""

		errors = {
			1: _('could not update password file'),
			2: _('invalid command syntax'),
			3: _('invalid argument to option'),
			4: _('UID already in use (and no -o)'),
			6: _('specified group doesnt exist'),
			9: _('username already in use'),
			10: _('could not update group file'),
			12: _('could not create home directory'),
			13: _('could not create mail spool'),
		}

		try:
			success = True
			message = ''

			# Username
			username = object.get('username')

			pwoptions = {}
			cmd = ['/usr/sbin/useradd', '-r']

			if username == object.get('group'):
				object['create_usergroup'] = True
				cmd.append('-U')
			else:
				cmd.append('-N')

			cmd += self._get_common_args( object, pwoptions )

			# Execute
			cmd.append(username)
			returncode = self.process(cmd)
			if 0 != returncode:
				MODULE.error("cmd '%s' failed with returncode %d" % (' '.join(map(str, cmd)), returncode))
				error = errors.get( returncode, _('unknown error with statuscode %d occurred') % (returncode) )
				raise ValueError( error )

			# Change Password + options
			password = object.get('password')
			self._change_user_password(username, password, pwoptions)
		except ValueError as e:
			success = False
			message = '%s%s' % ('%s: ' % username if isinstance(username, basestring) else '', e,)

		MODULE.info( 'luga.users_add: results: %s' % (message,) )
		return {'message': message, 'success': success}
def list_objects(container, object_type=None, ldap_connection=None, ldap_position=None):
	"""Yields UDM objects"""
	try:
		result = ldap_connection.search(base=container, scope='one')
	except (LDAPError, udm_errors.ldapError):
		raise
	except udm_errors.noObject:
		raise ObjectDoesNotExist(container)
	except udm_errors.ldapTimeout:
		raise SearchTimeoutError()
	except udm_errors.ldapSizelimitExceeded:
		raise SearchLimitReached()
	except udm_errors.base as exc:
		UDM_Error(exc).reraise()
	for dn, attrs in result:
		modules = udm_modules.objectType(None, ldap_connection, dn, attrs)
		if not modules:
			MODULE.warn('Could not identify LDAP object %r' % (dn,))
			continue
		if object_type == '$containers$' and not udm_modules.childs(modules[0]):
			continue
		if len(modules) > 1:
			MODULE.warn('Found multiple object types for %r: %r' % (dn, modules))
			MODULE.info('dn: %r, attrs: %r' % (dn, attrs))
		for mod in modules:
			module = UDM_Module(mod)
			if module.module:
				break

		if not module.module:
			MODULE.process('The UDM module %r could not be found. Ignoring LDAP object %r' % (modules[0], dn))
			continue
		if module.superordinate_names:
			for superordinate in module.superordinate_names:
				so_module = UDM_Module(superordinate)
				so_obj = so_module.get(container)
				try:
					yield (module, module.get(dn, so_obj, attributes=attrs))
				except BaseException:
					try:
						yield (module, module.get(dn, so_obj))
					except (UDM_Error, udm_errors.base):
						MODULE.error('Could not load object %r (%r) exception: %s' % (dn, module.module, traceback.format_exc()))
				break
		else:
			try:
				yield (module, module.get(dn, attributes=attrs))
			except BaseException:
				try:
					yield (module, module.get(dn))
				except (UDM_Error, udm_errors.base):
					MODULE.error('Could not load object %r (%r) exception: %s' % (dn, module.module, traceback.format_exc()))
Beispiel #39
0
    def net_dhclient(self, request):
        '''Request a DHCP address. Expects as options a dict containing the key
		"interface" and optionally the key "timeout" (in seconds).'''
        interface = request.options.get('interface')
        timeout = request.options.get('timeout', 45)
        if not interface:
            message = 'No property "interface" given for dhclient().'
            MODULE.error(message)
            self.finished(request.id, None, success=False, message=message)
            return

        res = util.dhclient(interface, timeout)
        self.finished(request.id, res)
Beispiel #40
0
	def lang_keymaps(self, request):
		'''Return a list of all available keyboard layouts.'''
		try:
			file = open('/lib/univention-installer/locale/all-kmaps')
		except:
			MODULE.error( 'Cannot find locale data for keymaps in /lib/univention-installer/locale' )
			self.finished(request.id, None)
			return

		r = csv.reader(file, delimiter=':')
		keymaps = [ { 'label': i[0], 'id': i[1] } for i in r if not i[0].startswith('#') ]

		self.finished(request.id, keymaps)
Beispiel #41
0
	def net_dhclient(self, request):
		'''Request a DHCP address. Expects as options a dict containing the key
		"interface" and optionally the key "timeout" (in seconds).'''
		interface = request.options.get('interface')
		timeout = request.options.get('timeout', 45)
		if not interface:
			message = 'No property "interface" given for dhclient().'
			MODULE.error(message)
			self.finished(request.id, None, success = False, message = message)
			return

		res = util.dhclient(interface, timeout)
		self.finished(request.id, res)
Beispiel #42
0
def cleanup():
	# write header before executing scripts
	f = open(LOG_FILE, 'a')
	f.write('\n\n=== Cleanup (%s) ===\n\n' % timestamp())
	f.flush()

	ucr = univention.config_registry.ConfigRegistry()
	ucr.load()

	# The browser was only started, if system/setup/boot/start is true
	if ucr.is_true('system/setup/boot/start', False):
		MODULE.info('Appliance mode: try to shut down the browser')
		try:
			fpid = open(PATH_BROWSER_PID)
			strpid = fpid.readline().strip()
			pid = int(strpid)
			p = psutil.Process(pid)
			p.kill()
		except IOError:
			MODULE.warn('cannot open browser PID file: %s' % PATH_BROWSER_PID)
		except ValueError:
			MODULE.error('browser PID is not a number: "%s"' % strpid)
		except psutil.NoSuchProcess:
			MODULE.error('cannot kill process with PID: %s' % pid)

		# Maybe the system-setup CMD tool was started
		for p in psutil.process_iter():
			if p.name == 'python2.6' and '/usr/share/univention-system-setup/univention-system-setup' in p.cmdline:
				p.kill()

	# unset the temporary interface if set
	for var in ucr.keys():
		if RE_IPV4_TYPE.match(var) and ucr.get(var) == 'appliance-mode-temporary':
			f.write('unset %s' % var)
			keys = [var]
			for k in ['netmask', 'address', 'broadcast', 'network']:
				keys.append(var.replace('/type', '/%s' % k))
			univention.config_registry.handler_unset(keys)
			# Shut down temporary interface
			subprocess.call(['ifconfig', var.split('/')[1].replace('_', ':'), 'down'])

	# force a restart of UMC servers and apache
	subprocess.call( CMD_DISABLE_EXEC, stdout = f, stderr = f )
	subprocess.call( CMD_ENABLE_EXEC_WITH_RESTART, stdout = f, stderr = f )

	f.write('\n=== DONE (%s) ===\n\n' % timestamp())
	f.flush()
	f.close()

	return True
Beispiel #43
0
	def restart(self, request):
		MODULE.error(str(request.arguments))
		if self.permitted('services/restart', request.options):
			message = {}
			message['success'] = _('Successfully restarted')
			message['failed'] = _('Restarting the following services failed:')
			cb = notifier.Callback(self._service_changed, request, message)
			func = notifier.Callback(self._run_it, request.options, 'restart')
			thread = notifier.threads.Simple('services', func, cb)
			thread.run()
		else:
			message = _('You are not permitted to run this command.')
			request.status = MODULE_ERR
			self.finished(request.id, None, message)
Beispiel #44
0
	def _check_error(self, request, partition_name): # TODO
		message = None
		try:
			fs = fstab.File()
			mt = mtab.File()
		except IOError as error:
			MODULE.error('Could not open %s' % error.filename)
			message = _('Could not open %s') % error.filename
		partition = fs.find(spec = partition_name)
		if partition:
			mounted_partition = mt.get(partition.spec)
			if mounted_partition:
				if 'usrquota' not in mounted_partition.options:
					MODULE.error('The following partition is mounted '
					             'without quota support: %s' % partition_name)
					message = _('The following partition is mounted mounted '
					            'without quota support: %s') % partition_name
			else:
				MODULE.error('The following partition is '
				             'currently not mounted: %s' % partition_name)
				message = _('The following partition is currently '
				            'not mounted: %s') % partition_name
		else:
			MODULE.error('No partition found (%s)' % partition_name)
			message = _('No partition found (%s)') % partition_name
		if message:
			request.status = MODULE_ERR
			self.finished(request.id, None, message)
Beispiel #45
0
	def kill(self, request):
		failed = []
		message = ''
		signal = request.options.get('signal', 'SIGTERM')
		pidList = request.options.get('pid', [])
		for pid in pidList:
			try:
				process = psutil.Process(int(pid))
				if signal == 'SIGTERM':
					process.kill(15)
				elif signal == 'SIGKILL':
					process.kill(9)
			except psutil.NoSuchProcess, error:
				failed.append(pid)
				MODULE.error(str(error))
Beispiel #46
0
def genConfigs(server):
	ucr.load()
	MODULE.error('### server: %s' % server)
	co = server.co
	lo = server.lo

	configs = {
		'sip.conf': genSipconf(co, lo, server),
		'voicemail.conf': genVoicemailconf(co, lo, server),
		'queues.conf': genQueuesconf(co, lo, server),
		'musiconhold.conf': genMusiconholdconf(co, lo, server),
		'extensions.conf': genExtensionsconf(co, lo, server),
	}

	return configs
Beispiel #47
0
	def groups_add(self, request):
		if not type(request.options) == list:
			raise UMC_OptionTypeError(_('Options have to be given as list of dictionarys.'))

		messages = []
		for group in request.options:
			options = None
			groupname = None
			users = None
			command = ['/usr/sbin/groupadd']
			exit_code = None

			try:
				if not type(group) == dict:
					raise ValueError(_('Invalid optiontype.'))
				options = group.get('object', {})
				if not type(options) == dict:
					raise ValueError(_('Invalid optiontype.'))

				groupname = options.get('groupname')
				users = options.get('users')

				if not groupname is not None:
					raise ValueError(_('Groupname is required.'))
				if not type(groupname) == str:
					raise ValueError(_('Groupname has to be given as string.'))
				self.validate_name(groupname)
				command += [groupname]

				# execute "groupadd"
				exit_code = self.process(command)
				if exit_code == 9:
					raise ValueError(_('Groupname "%s" is already in use.') % groupname)
				if exit_code:
					MODULE.error('Processing "%s" failed and returned %s' % (str(command), str(exit_code)))
					raise CreatingError(_('Could not create group. See log for more information.'))
				if users is not None:
					if not type(users) == list:
						raise ModifyError(_('Users have to be given as list.'))
					if self.process(['/usr/bin/gpasswd', '-M', ','.join(users), groupname]):
						raise ModifyError(_('Could not set list of users.'))
			except (ValueError, CreatingError, ModifyError) as e:
				messages += [str(e)]
				if type(e) == ModifyError:
					self.process(['/usr/sbin/groupdel', groupname])
			else:
				messages += ['']
		self.finished(request.id, messages)
Beispiel #48
0
	def dump_data(self):
		# we could return infos we have in this object itself.
		# but dont be too clever here. just dump
		# everything we have in LDAP.
		try:
			_lo = uldap.getMachineConnection()
			data = _lo.search('objectClass=univentionLicense')
			del _lo
			# just one license (should be always the case)
			# return the dictionary without the dn
			data = ldif.CreateLDIF(data[0][0], data[0][1])
			return data
		except Exception as e:
			# no udm, no ldap, malformed return value, whatever
			MODULE.error('getting License from LDAP failed: %s' % e)
			return None
Beispiel #49
0
	def process(self, args, stdin=None):
		"""
			process a shell command
			
			:param list args: list of command and arguments
			:param str stdin: stdin input
			:returns: int returncode
		"""

		try:
			args = map(lambda a: str(a).encode('utf-8'), args)
			p = Popen( args = args, stderr = PIPE, stdin = PIPE )
			(stdout, stderr) = p.communicate(stdin)
			MODULE.debug('%s: stdout=%s; stderr=%s' % (' '.join(args)), stdout, stderr )
		except OSError as e:
			MODULE.error( 'Command failed: %s\nException: %s' % (args, str(e)) )
			raise ValueError( _('Command failed') )

		return p.returncode
Beispiel #50
0
	def users_remove(self, object, options={}):
		"""
			remove a list of local users
			param request.options = [ { username: <string>, force: <bool>, remove: <bool> }, ...]
				force: force removal of files, even if not owned by user
				remove: remove home directory and mail spool
			# TODO: message could be a dict with success and message
		"""

		errors = {
			1: _('could not update password file'),
			2: _('invalid command syntax'),
			6: _('specified user doesnt exist'),
			8: _('user currently logged in'),
			10: _('could not update group file'),
			12: _('could not remove home directory or mail spool')
		}

		try:
			success = True
			message = ''

			cmd = ['/usr/sbin/userdel']
			username = object

			if options.get('force'):
				cmd.append('-f')
			if options.get('remove'):
				cmd.append('-r')

			cmd.append(username)

			returncode = self.process(cmd)
			if returncode != 0:
				MODULE.error("cmd '%s' failed with returncode %d" % (' '.join(map(str, cmd)), returncode))
				error = errors.get( returncode, _('unknown error with statuscode %d occurred') % (returncode) )
				raise ValueError( error )
		except ValueError as e:
			success = False
			message = '%s%s' % ('%s: ' % username if isinstance(username, basestring) else '', e,)

		return {'message': message, 'success': success}
Beispiel #51
0
    def init(self):
        try:
            if self.init_called:
                MODULE.warn("init() called multiple times!")
                return
            self.init_called = True
            MODULE.info("Initializing 'updater' module (PID = %d, LANG = '%s')" % (getpid(), self.locale))

            self.uu = UniventionUpdater(False)
            self.ucr = univention.config_registry.ConfigRegistry()
            self.ucr.load()

            self._changes = {}  # collects changed UCR vars, for committing the corresponding files
            self._current_job = {}  # remembers last seen status of an installer job

            self._serial_file = Watched_File(COMPONENTS_SERIAL_FILE)
            self._updates_serial = Watched_Files(UPDATE_SERIAL_FILES)

        except Exception, ex:
            MODULE.error("init() ERROR: %s" % str(ex))
Beispiel #52
0
	def lang_countrycodes(self, request):
		'''Return a list of all countries with their two letter chcountry codes.'''
		try:
			file = open('/lib/univention-installer/locale/country_codes')
		except:
			MODULE.error( 'Cannot find locale data for keymaps in /lib/univention-installer/locale' )
			self.finished(request.id, None)
			return

		r = csv.reader(file, delimiter=':')
		countries = [ { 'label': i[0], 'id': i[1] } for i in r if not i[0].startswith('#') ]

		# add the value from ucr value to the list
		# this is required because invalid values will be unset in frontend
		# Bug #26409
		tmpUCR = univention.config_registry.ConfigRegistry()
		tmpUCR.load()
		ssl_country = tmpUCR.get('ssl/country')
		if ssl_country not in [ i['id'] for i in countries ]:
			countries.append( {'label': ssl_country, 'id': ssl_country} )

		self.finished(request.id, countries)
Beispiel #53
0
	def get_system_info(self, request):
		MANUFACTURER = request.options['manufacturer'].encode( 'utf-8' )
		MODEL = request.options['model'].encode( 'utf-8' )
		COMMENT = request.options['comment'].encode( 'utf-8' )
		SYSTEM_INFO_CMD = ( '/usr/bin/univention-system-info',
							'-m', MANUFACTURER,
							'-t', MODEL,
							'-c', COMMENT,
							'-s', request.options.get('ticket', ''),
							'-u', )

		(exitcode, stdout, stderr, ) = self._call(SYSTEM_INFO_CMD)
		if exitcode:
			MODULE.error('Execution of univention-system-info failed: %s'
			             % stdout)
			result = None
			request.status = MODULE_ERR
		else:
			result = {}
			for line in stdout.splitlines():
				try:
					info, value = line.split(':')
					result[info] = value
				except:
					pass
			if result['mem']:
				match = self.mem_regex.match(result['mem'])
				if match:
					try:
						converted_mem = (float(match.groups()[0]) / 1048576)
						result['mem'] = '%.2f GB' % converted_mem
						result['mem'] = request['mem'].replace('.', ',')
					except:
						pass
			if result['Temp']:
				del result['Temp'] # remove unnecessary entry
			request.status = SUCCESS

		self.finished(request.id, result)
Beispiel #54
0
	def groups_remove(self, request):
		if not type(request.options) == list:
			raise UMC_OptionTypeError(_('Options have to be given as list of strings.'))

		messages = []
		user_cache = self._parse_users()
		for group in request.options:
			identifier = group.get('object', '').replace('&lt;', '<') # frontend converts '<' to '&lt' for some reasons (undo that)
			gid = None
			primary_users = []
			command = ['/usr/sbin/groupdel']
			exit_code = None

			try:
				if not type(identifier) == str:
					raise ValueError(_('ID has to be given as string.'))

				# iterate over all users to check if one of them has the group as primary group
				for cached_user in user_cache:
					if cached_user['gid'] == gid:
						primary_users += [cached_user['username']]
				if primary_users: # users found wich have the group as primary group?
					raise ModifyError(_('Can not remove the primary group of user(s): %s.') % ', '.join(primary_users))

				command += [identifier]

				# execute "groupdel"
				exit_code = self.process(command)
				if exit_code == 6:
					raise ModifyError(_('Group "%s" does not exist.') % identifier)
				if exit_code:
					raise ModifyError(_('Could not delete group "%s". See log for more informaton.') % identifier)
					MODULE.error('Processing "%s" failed and returned %s' % (str(command), str(exit_code)))
			except (ValueError, ModifyError) as e:
				messages += ['%s: %s' % (identifier, str(e))]
			else:
				messages += ['']
		self.finished(request.id, messages)
Beispiel #55
0
	def create(self, request):
		server = getServer(request.options["server"])
		MODULE.error('### request: %s' % request)
		MODULE.error('### self: %s' % self)
		MODULE.error('### values: %s' % request.options.get('values', {}))
		log = openLog(server["commonName"])
		createConfigs(log, server)
		closeLog(log)
		self.finished(request.id, True)
Beispiel #56
0
		def _thread(request, obj):
			# acquire the lock until the scripts have been executed
			self._finishedResult = False
			obj._finishedLock.acquire()
			try:
				self._progressParser.reset()

				# write the profile file and run setup scripts
				orgValues = util.load_values()
				util.pre_save(values, orgValues)

				MODULE.info('saving profile values')
				util.write_profile(values)

				if not values:
					MODULE.error( 'No property "values" given for save().' )
					return False

				# in case of changes of the IP address, restart UMC server and web server
				# for this we ignore changes of virtual or non-default devices
				MODULE.info('Check whether ip addresses have been changed')
				restart = False
				for ikey, ival in values.iteritems():
					if RE_IPV4.match(ikey) or RE_IPV6_DEFAULT.match(ikey) or RE_SSL.match(ikey):
						restart = True
						break
				MODULE.info('Restart servers: %s' % restart)

				# on a joined system or on a basesystem, we can run the setup scripts
				MODULE.info('runnning system setup scripts')
				util.run_scripts( self._progressParser, restart )

				# done :)
				self._finishedResult = True
				return True
			finally:
				obj._finishedLock.release()
Beispiel #57
0
def get_available_locales(pattern, category='language_en'):
	'''Return a list of all available locales.'''
	try:
		fsupported = open('/usr/share/i18n/SUPPORTED')
		flanguages = open('/lib/univention-installer/locale/languagelist')
	except:
		MODULE.error( 'Cannot find locale data for languages in /lib/univention-installer/locale' )
		return

	# get all locales that are supported
	rsupported = csv.reader(fsupported, delimiter=' ')
	supportedLocales = { 'C': True }
	for ilocale in rsupported:
		# we only support UTF-8
		if ilocale[1] != 'UTF-8':
			continue

		# get the locale
		m = RE_LOCALE.match(ilocale[0])
		if m:
			supportedLocales[m.groups()[0]] = True

	category = {'langcode': 0, 'language_en': 1, 'language': 2, 'countrycode': 4, 'fallbacklocale': 5}.get(category, 1)

	# open all languages
	rlanguages = csv.reader(flanguages, delimiter=';')
	locales = []
	for ilang in rlanguages:
		if ilang[0].startswith('#'):
			continue

		if not pattern.match(ilang[category]):
			continue

		# each language might be spoken in several countries
		ipath = '/lib/univention-installer/locale/short-list/%s.short' % ilang[0]
		if os.path.exists(ipath):
			try:
				# open the short list with countries belonging to the language
				fshort = open(ipath)
				rshort = csv.reader(fshort, delimiter='\t')

				# create for each country a locale entry
				for jcountry in rshort:
					code = '%s_%s' % (ilang[0], jcountry[0])
					if code in supportedLocales:
						locales.append({
							'id': '%s.UTF-8:UTF-8' % code,
							'label': '%s (%s)' % (ilang[1], jcountry[2])
						})
				continue
			except Exception:
				pass

		# get the locale code
		code = ilang[0]
		if code.find('_') < 0 and code != 'C':
			# no underscore -> we need to build the locale ourself
			code = '%s_%s' % (ilang[0], ilang[4])

		# final entry
		if code in supportedLocales:
			locales.append({
				'id': '%s.UTF-8:UTF-8' % code,
				'label': ilang[1]
			})

	return locales
Beispiel #58
0
	def groups_put(self, request):
		if not type(request.options) == list:
			raise UMC_OptionTypeError(_('Options have to be given as list of dictionarys.'))

		messages = []
		for group in request.options:
			group_index = None
			command = ['/usr/sbin/groupmod']
			options = None
			identifier = None
			groupname = None
			users = None
			exit_code = None

			try:
				if not type(group) == dict:
					raise ValueError(_('Invalid optiontype.'))
				options = group.get('object', {})
				if not type(options) == dict:
					raise ValueError(_('Invalid opiontype.'))

				identifier = options.get('$groupname$')
				groupname = options.get('groupname')
				gid = options.get('gid')
				users = options.get('users')

				if not identifier:
					raise ValueError(_('No group has been specified.'))
				if not type(identifier) == str:
					raise ValueError(_('ID has to be given as string.'))
				command += [identifier]
				if groupname is None and gid is None and users is None and administrators is None:
					raise ModifyError(_('No changes have been made.'))

				# first try to set new list of users, if given, with "gpasswd"
				if users is not None:
					if self.process(['/usr/bin/gpasswd', '-M', ','.join(users), identifier]):
						raise ModifyError(_('Could not modify list of users.'))

				# collect arguements for "groupmod" command
				if groupname is not None:
					self.validate_name(groupname)
					command += ['-n', groupname]
				if gid is not None:
					if not type(gid) == int:
						raise ValueError(_('"Group ID has to be given as string.'))
					command += ['-g', '%s' % gid]

				# exceute "groupmod"
				exit_code = self.process(command)
				if exit_code == 3:
					raise ValueError(_('"%s" is no valid Group ID. Group IDs may only consit of digits.') % gid)
				if exit_code == 4:
					raise ValueError(_('Group ID "%s" is already in use.') % gid)
				if exit_code == 6:
					raise ModifyError(_('Group "%s" does not exist.') % identifier)
				if exit_code == 9:
					raise ValueError(_('Groupname "%s" is already in use.') % groupname)
				if exit_code:
					MODULE.error('Processing "%s" failed and returned %s' % (str(command), str(exit_code)))
					raise ModifyError(_('Could not modify group. See log for more information.'))
			except (ValueError, ModifyError) as e:
				messages += [str(e)]
			else:
				messages += ['']
		self.finished(request.id, messages)