def __init__(self, db): self.db = db self.const = Factory.get('Constants')(db) self.account = Factory.get('Account')(db) self.posix_user = Factory.get('PosixUser')(db) self.disk_quota = DiskQuota(db) self.disk_mapping = OUDiskMapping(db)
def list_disk_quotas(f, disk_id, spread): account = Factory.get("Account")(db) disk = Factory.get("Disk")(db) disk.find(disk_id) if not disk.has_quota(): logger.debug("Skipping %s, no quotas on disk" % disk.path) return default_quota = disk.get_default_quota() logger.debug("Listing quotas on %s" % disk.path) if default_quota is None: default_quota = '' # Unlimited all_users = False else: all_users = True now = mx.DateTime.now() dq = DiskQuota(db) for row in dq.list_quotas(spread=spread, disk_id=disk.entity_id, all_users=all_users): quota = row['quota'] if row['override_expiration'] and row['override_expiration'] > now: quota = row['override_quota'] if quota is None: quota = default_quota home = account.resolve_homedir(account_name=row['entity_name'], home=row['home'], disk_path=row['path']) f.write("%s:%s:%s\n" % (row['entity_name'], home, quota))
def clear_home(self, spread): """Remove disk quota before clearing home.""" try: homeinfo = self.get_home(spread) except Errors.NotFoundError: pass else: dq = DiskQuota(self._db) dq.clear(homeinfo['homedir_id']) return self.__super.clear_home(spread)
def determine_disks(self, account, request_id, profile, fnr): disks = [] spreads = [int(s) for s in profile.get_spreads()] try: for d_spread in profile.get_disk_spreads(): if d_spread != self.default_spread: # TBD: How can all spreads be taken into account? continue if d_spread in spreads: try: ah = account.get_home(d_spread) homedir_id = ah['homedir_id'] current_disk_id = ah['disk_id'] except Errors.NotFoundError: homedir_id, current_disk_id = None, None if self.autostud.disk_tool.get_diskdef_by_diskid( int(current_disk_id)): logger.debug("Already on a student disk") self.br.delete_request(request_id=request_id) self.db.commit() # actually, we remove a bit too much data from # the below dict, but remaining data will be # rebuilt on next run. del (self.fnr2move_student[fnr]) raise NextAccount try: new_disk = profile.get_disk(d_spread, current_disk_id, do_check_move_ok=False) if new_disk == current_disk_id: continue disks.append((new_disk, d_spread)) if (self.autostud.disk_tool.using_disk_kvote and homedir_id is not None): from Cerebrum.modules.disk_quota import DiskQuota disk_quota_obj = DiskQuota(self.db) try: cur_quota = disk_quota_obj.get_quota( homedir_id) except Errors.NotFoundError: cur_quota = None quota = profile.get_disk_kvote(new_disk) if (cur_quota is None or cur_quota['quota'] != int(quota)): disk_quota_obj.set_quota(homedir_id, quota=int(quota)) except AutostudError, msg: # Will end up on pending (since we only use one # spread) logger.debug("Error getting disk: %s" % msg) break except NextAccount: pass # Stupid python don't have labeled breaks return disks
def set_homedir(self, *args, **kw): """Remove quota information when the user is moved to a disk without quotas or where the default quota is larger than his existing explicit quota.""" ret = self.__super.set_homedir(*args, **kw) if kw.get('current_id') and kw.get('disk_id'): disk = Factory.get("Disk")(self._db) disk.find(kw['disk_id']) has_quota = disk.has_quota() def_quota = disk.get_default_quota() dq = DiskQuota(self._db) try: info = dq.get_quota(kw['current_id']) except Errors.NotFoundError: pass else: if not has_quota: # No quota on new disk, so remove the quota information. dq.clear(kw['current_id']) elif def_quota is None: # No default quota, so keep the quota information. pass else: if (info['override_expiration'] and DateTime.now() < info['override_expiration']): old_quota = info['override_quota'] else: old_quota = info['quota'] if old_quota <= def_quota: dq.clear(kw['current_id']) return ret
db = Factory.get('Database')() db.cl_init(change_program='process_students') const = Factory.get('Constants')(db) derived_person_affiliations = {} person_student_affiliations = {} processed_students = {} processed_accounts = {} keep_account_home = {} account_id2fnr = {} posix_tables = False posix_user_obj = Factory.get('PosixUser')(db) account_obj = Factory.get('Account')(db) person_obj = Factory.get('Person')(db) group_obj = Factory.get('Group')(db) disk_quota_obj = DiskQuota(db) debug = 0 max_errors = 50 # Max number of errors to accept in person-callback posix_spreads = [int(const.Spread(_s)) for _s in cereconf.POSIX_SPREAD_CODES] # global Command-line alterable variables. Defined here to make # pychecker happy skip_lpr = True # Must explicitly tell that we want lpr create_users = move_users = dryrun = update_accounts = False with_quarantines = False remove_groupmembers = False ou_perspective = None workdir = None student_info_file = None studconfig_file = None
def _clear_homedir(self, homedir_id): # Since disk_quota has a FK to homedir, we need this override dq = DiskQuota(self._db) dq.clear(homedir_id) return self.__super._clear_homedir(homedir_id)
class AccountPolicy(object): def __init__(self, db): self.db = db self.const = Factory.get('Constants')(db) self.account = Factory.get('Account')(db) self.posix_user = Factory.get('PosixUser')(db) self.disk_quota = DiskQuota(db) self.disk_mapping = OUDiskMapping(db) def create_basic_account(self, creator_id, owner, uname, np_type=None): self.account.clear() if not self.account.is_valid_new_uname: raise InvalidAccountCreationArgument('Username already taken: %r' % uname) self.account.populate(uname, owner.entity_type, owner.entity_id, np_type, creator_id, None) self.account.write_db() new_account = Factory.get('Account')(self.db) new_account.find(self.account.entity_id) return new_account def create_group_account(self, creator_id, uname, owner_group, contact_address, account_type): account = self.create_basic_account(creator_id, owner_group, uname, account_type) if not is_email(contact_address): raise InvalidAccountCreationArgument('Invalid email address: %s', contact_address) # Unpersonal accounts shouldn't normally have a mail inbox, but they # get a forward target for the account, to be sent to those responsible # for the account, preferrably a sysadm mail list. if hasattr(account, 'add_contact_info'): account.add_contact_info(self.const.system_manual, self.const.contact_email, contact_address) if cereconf.BOFHD_CREATE_UNPERSONAL_QUARANTINE: qconst = self.const.Quarantine( cereconf.BOFHD_CREATE_UNPERSONAL_QUARANTINE ) account.add_entity_quarantine(qconst, creator_id, "Not granted for global password " "auth (ask IT-sikkerhet)", datetime.date.today().isoformat()) return account def _make_posix_user(self, gid, gecos, shell, expire_date): self.posix_user.clear() uid = self.posix_user.get_free_uid() self.posix_user.populate( uid, gid, gecos, shell, parent=self.account, expire_date=expire_date ) self.posix_user.write_db() def _set_user_disk(self, account, disk_id, home_spread, home=None, disk_quota=None): if home: homedir_id = account.set_homedir( disk_id=disk_id, status=self.const.home_status_not_created, home=home ) else: homedir_id = account.set_homedir( disk_id=disk_id, status=self.const.home_status_not_created ) account.set_home(home_spread, homedir_id) if disk_quota: self.disk_quota.set_quota(homedir_id, quota=int(disk_quota)) def _get_ou_disk(self, person): # Get highest precedent affiliation _, ou_id, aff, _, status, _, _, _, _ = person.list_affiliations( person.entity_id)[0] # Find the right disk id for this person if aff: aff = self.const.PersonAffiliation(aff) if status: status = self.const.PersonAffStatus(status) disk_id = utils.get_disk( self.db, self.disk_mapping, ou_id, aff, status, self.const.OUPerspective(cereconf.DEFAULT_OU_PERSPECTIVE)) home_spread = int(self.const.Spread(cereconf.DEFAULT_HOME_SPREAD)) return disk_id, home_spread def update_account(self, person, account_id, *args, **kwargs): self.account.clear() self.account.find(account_id) return self._update_account(person, *args, **kwargs) def _update_account(self, person, affiliations, disks, expire_date, traits=(), spreads=(), make_posix_user=True, gid=None, shell=None, ou_disk=False): """Update an account Adds traits, spreads and disks to an account, and also promotes posix. Note self.account must already populated. """ for trait in traits: self.account.populate_trait(code=trait, date=datetime.date.today()) self.account.write_db() if make_posix_user: self._make_posix_user(gid, None, shell, expire_date) user = self._get_user_obj(make_posix_user) for spread in spreads: user.add_spread(spread) if ou_disk and not disks: disk_id, home_spread = self._get_ou_disk(person) disks = ({'disk_id': disk_id, 'home_spread': home_spread},) for disk in disks: self._set_user_disk(user, disk['disk_id'], disk['home_spread'], home=disk.get('home', None), disk_quota=disk.get('disk_quota', None)) _set_account_types(user, person, affiliations) user.write_db() return user def _get_user_obj(self, posix): if posix: return self.posix_user else: return self.account def create_personal_account(self, person, affiliations, disks, expire_date, creator_id, uname=None, traits=(), spreads=(), make_posix_user=True, gid=None, shell=None, ou_disk=False): """Create a personal account for the given person :type person: populated Cerebrum.Utils._dynamic_Person :type affiliations: dicts containing keys 'affiliation' and 'ou_id' :param affiliations: affiliations to set on the account :type disks: Iterable :param disks: disks to give the user. Each disk is a dict with the required keys 'disk_id', 'home_spread' and optional keys 'home', 'disk_quota'. :param uname: the desired user name :param traits: traits to add to the newly created account :param spreads: spreads to add to the newly created account :param make_posix_user: should the account be a posix user? :type ou_disk: bool :param ou_disk: should a disk be selected using the OUDiskMapping module if disks parameter is empty? :return: Account or PosixUser """ user = self._get_user_obj(make_posix_user) if uname is None: try: user_names = user.suggest_unames(person) except NotFoundError: raise InvalidAccountCreationArgument( 'Person %s missing first- or lastname', person.entity_id ) try: uname = user_names[0] except IndexError: raise InvalidAccountCreationArgument( 'Could not generate user name for person %s', person.entity_id ) self.account.clear() self.account.populate(uname, self.const.entity_person, person.entity_id, None, creator_id, expire_date) self.account.write_db() user = self._update_account(person, affiliations, disks, expire_date, traits=traits, spreads=spreads, make_posix_user=make_posix_user, gid=gid, shell=shell, ou_disk=ou_disk) # Returning a new account object to avoid accidentally modifying the # current one when creating another account. if make_posix_user: new_account = Factory.get('PosixUser')(self.db) else: new_account = Factory.get('Account')(self.db) new_account.find(user.entity_id) return new_account