Exemple #1
0
class SelfServiceUser(object):
    def __init__(self, username, password):
        self._client = Client()
        self.username = username
        self.password = password

    def request(self, uri, **kwargs):
        options = {'username': self.username, 'password': self.password}
        options.update(kwargs)
        return self._client.umc_command(uri, options)
        # TODO: kill all self-service UMC module processes because 1 process per request sums up and blocks resources for 15 minutes

    def get_contact(self):
        return dict(
            (data['id'], data['value'])
            for data in self.request('passwordreset/get_contact').result)

    def set_contact(self, email='', mobile=''):
        return self.request('passwordreset/set_contact',
                            email=email,
                            mobile=mobile).result

    def get_reset_methods(self):
        return [
            x['id']
            for x in self.request('passwordreset/get_reset_methods').result
        ]

    def send_token(self, method):
        return self.request('passwordreset/send_token', method=method).result

    def set_password(self, token, password):
        return self.request('passwordreset/set_password',
                            token=token,
                            password=password).result
Exemple #2
0
class UmcComputer(object):
    def __init__(self,
                 school,
                 typ,
                 name=None,
                 ip_address=None,
                 subnet_mask=None,
                 mac_address=None,
                 inventory_number=None):
        self.school = school
        self.typ = typ
        self.name = name if name else uts.random_name()
        self.ip_address = ip_address if ip_address else random_ip()
        self.subnet_mask = subnet_mask if subnet_mask else '255.255.255.0'
        self.mac_address = mac_address.lower() if mac_address else random_mac()
        self.inventory_number = inventory_number if inventory_number else ''
        self.ucr = ucr_test.UCSTestConfigRegistry()
        self.ucr.load()
        host = self.ucr.get('ldap/master')
        self.client = Client(host)
        account = utils.UCSTestDomainAdminCredentials()
        admin = account.username
        passwd = account.bindpw
        self.client.authenticate(admin, passwd)

    def create(self, should_succeed=True):
        """Creates object Computer"""
        flavor = 'schoolwizards/computers'
        param = [{
            'object': {
                'school': self.school,
                'type': self.typ,
                'name': self.name,
                'ip_address': self.ip_address,
                'mac_address': self.mac_address.lower(),
                'subnet_mask': self.subnet_mask,
                'inventory_number': self.inventory_number
            },
            'options': None
        }]
        print 'Creating Computer %s' % (self.name, )
        print 'param = %s' % (param, )
        reqResult = self.client.umc_command('schoolwizards/computers/add',
                                            param, flavor).result
        if reqResult[0] == should_succeed:
            utils.wait_for_replication()
        elif should_succeed in reqResult[0]['result']['message']:
            print 'Expected creation fail for computer (%r)\nReturn Message: %r' % (
                self.name, reqResult[0]['result']['message'])
        else:
            raise CreateFail(
                'Unable to create computer (%r)\nRequest Result: %r' %
                (param, reqResult))

    def remove(self):
        """Remove computer"""
        flavor = 'schoolwizards/computers'
        param = [{
            'object': {
                '$dn$': self.dn(),
                'school': self.school,
            },
            'options': None
        }]
        reqResult = self.client.umc_command('schoolwizards/computers/remove',
                                            param, flavor).result
        if not reqResult[0]:
            raise RemoveFail('Unable to remove computer (%s)' % self.name)
        else:
            utils.wait_for_replication()

    def dn(self):
        return 'cn=%s,cn=computers,%s' % (
            self.name, utu.UCSTestSchool().get_ou_base_dn(self.school))

    def get(self):
        """Get Computer"""
        flavor = 'schoolwizards/computers'
        param = [{'object': {'$dn$': self.dn(), 'school': self.school}}]
        reqResult = self.client.umc_command('schoolwizards/computers/get',
                                            param, flavor).result
        if not reqResult[0]:
            raise GetFail('Unable to get computer (%s)' % self.name)
        else:
            return reqResult[0]

    def check_get(self):
        info = {
            '$dn$': self.dn(),
            'school': self.school,
            'type': self.typ,
            'name': self.name,
            'ip_address': [self.ip_address],
            'mac_address': [self.mac_address.lower()],
            'subnet_mask': self.subnet_mask,
            'inventory_number': self.inventory_number,
            'zone': None,
            'type_name': self.type_name(),
            'objectType': 'computers/%s' % self.typ
        }
        get_result = self.get()
        if get_result != info:
            diff = set(x for x in get_result if get_result[x] != info[x])
            raise GetCheckFail(
                'Failed get request for computer %s.\nReturned result: %r.\nExpected result: %r,\nDifference = %r'
                % (self.name, get_result, info, diff))

    def type_name(self):
        if self.typ == 'windows':
            return 'Windows-System'
        elif self.typ == 'macos':
            return 'Mac OS X'
        elif self.typ == 'ipmanagedclient':
            return 'Gerät mit IP-Adresse'

    def edit(self, new_attributes):
        """Edit object computer"""
        flavor = 'schoolwizards/computers'
        param = [{
            'object': {
                '$dn$':
                self.dn(),
                'name':
                self.name,
                'school':
                self.school,
                'type':
                self.typ,
                'ip_address':
                new_attributes.get('ip_address')
                if new_attributes.get('ip_address') else self.ip_address,
                'mac_address':
                new_attributes.get('mac_address').lower()
                if new_attributes.get('mac_address') else self.mac_address,
                'subnet_mask':
                new_attributes.get('subnet_mask')
                if new_attributes.get('subnet_mask') else self.subnet_mask,
                'inventory_number':
                new_attributes.get('inventory_number')
                if new_attributes.get('inventory_number') else
                self.inventory_number,
            },
            'options': None
        }]
        print 'Editing computer %s' % (self.name, )
        print 'param = %s' % (param, )
        reqResult = self.client.umc_command('schoolwizards/computers/put',
                                            param, flavor).result
        if not reqResult[0]:
            raise EditFail(
                'Unable to edit computer (%s) with the parameters (%r)' %
                (self.name, param))
        else:
            self.ip_address = new_attributes.get('ip_address')
            self.mac_address = new_attributes.get('mac_address').lower()
            self.subnet_mask = new_attributes.get('subnet_mask')
            self.inventory_number = new_attributes.get('inventory_number')
            utils.wait_for_replication()

    def query(self):
        """get the list of existing computer in the school"""
        flavor = 'schoolwizards/computers'
        param = {'school': self.school, 'filter': "", 'type': 'all'}
        reqResult = self.client.umc_command('schoolwizards/computers/query',
                                            param, flavor).result
        return reqResult

    def check_query(self, computers):
        q = self.query()
        k = [x['name'] for x in q]
        if not set(computers).issubset(set(k)):
            raise QueryCheckFail(
                'computers from query do not contain the existing computers, found (%r), expected (%r)'
                % (k, computers))

    def verify_ldap(self, should_exist):
        print 'verifying computer %s' % self.name
        utils.verify_ldap_object(self.dn(), should_exist=should_exist)
Exemple #3
0
class QuotaCheck(object):

	def __init__(self, quota_type="usrquota", fs_type="ext4"):
		ucr = ucr_test.UCSTestConfigRegistry()
		ucr.load()
		self.ldap_base = ucr.get('ldap/base')
		self.my_fqdn = '%s.%s' % (ucr.get('hostname'), ucr.get('domainname'))
		account = utils.UCSTestDomainAdminCredentials()
		self.umc_client = Client(self.my_fqdn, username=account.username, password=account.bindpw)
		self.share_name = uts.random_name()
		self.share_name2 = uts.random_name()
		self.username = uts.random_name()
		self.quota_type = quota_type
		self.fs_type = fs_type

	def _activate_quota(self, loop_dev):
		print("Enable quota")
		options = {"partitionDevice": loop_dev}
		self.umc_client.umc_command('quota/partitions/activate', options).result

	def _check_quota_settings(self, loop_dev, expected_values={}):
		print("Check quota settings")
		options = {"filter": "*", "partitionDevice": loop_dev}
		user_quotas = self.umc_client.umc_command('quota/users/query', options).result
		expected_user_quota = {
			u'fileLimitHard': u'{}'.format(expected_values.get('fhard', 15)),
			u'fileLimitSoft': u'{}'.format(expected_values.get('fsoft', 10)),
			u'fileLimitTime': u'-',
			u'fileLimitUsed': u'1',
			u'id': u'{}@{}'.format(self.username, loop_dev),
			u'partitionDevice': u'{}'.format(loop_dev),
			u'sizeLimitHard': float(expected_values.get('bhard', 4)),
			u'sizeLimitSoft': float(expected_values.get('bsoft', 1)),
			u'sizeLimitTime': u'-',
			u'sizeLimitUsed': float(0),
			u'user': u'{}'.format(self.username),
		}
		print(expected_user_quota)
		assert expected_user_quota in user_quotas, "Quota was not set through pam"

	def test_quota_pam(self):
		with TempFilesystem(self.quota_type, fs_type=self.fs_type) as tfs, udm_test.UCSTestUDM() as udm:
			quota_policy = {
				"inodeSoftLimit": '10',
				"inodeHardLimit": '15',
				"spaceSoftLimit": str(1024 ** 2),
				"spaceHardLimit": str(2048 ** 2),
				"reapplyQuota": 'TRUE',
				"name": uts.random_name(),
			}

			self._activate_quota(tfs.loop_dev)
			print("Create Share")
			share = udm.create_object(
				'shares/share', name=self.share_name, path=tfs.mount_point, host=self.my_fqdn, directorymode="0777"
			)
			utils.wait_for_replication_and_postrun()
			qc.cache_must_exists(share)
			print("Create user")
			udm.create_user(username=self.username, check_for_drs_replication=False, wait_for=False)
			print("Create quota policy")
			policy = self.create_quota_policy(udm, quota_policy)
			print("Append quota policy")
			udm.modify_object("shares/share", dn=share, policy_reference=policy)
			utils.wait_for_replication_and_postrun()
			qc.check_values(
				share,
				quota_policy["inodeSoftLimit"],
				quota_policy["inodeHardLimit"],
				quota_policy["spaceSoftLimit"],
				quota_policy["spaceHardLimit"],
				quota_policy["reapplyQuota"]
			)
			self.touch_file(tfs.mount_point)
			self._check_quota_settings(tfs.loop_dev)

	def test_quota_pam_policy_removal(self):
		with TempFilesystem(self.quota_type, fs_type=self.fs_type) as tfs, udm_test.UCSTestUDM() as udm:
			quota_policy = {
				"inodeSoftLimit": '10',
				"inodeHardLimit": '15',
				"spaceSoftLimit": str(1024 ** 2),
				"spaceHardLimit": str(2048 ** 2),
				"reapplyQuota": 'TRUE',
				"name": uts.random_name(),
			}
			expected_result = {
				'bsoft': 1,
				'bhard': 4,
				'fsoft': 10,
				'fhard': 15
			}

			self._activate_quota(tfs.loop_dev)
			print("Create Share")
			share = udm.create_object(
				'shares/share', name=self.share_name, path=tfs.mount_point, host=self.my_fqdn, directorymode="0777"
			)
			utils.wait_for_replication_and_postrun()
			qc.cache_must_exists(share)
			print("Create user")
			udm.create_user(username=self.username, check_for_drs_replication=False)
			print("Create quota policy")
			policy = self.create_quota_policy(udm, quota_policy)
			print("Append quota policy")
			udm.modify_object("shares/share", dn=share, policy_reference=policy)
			utils.wait_for_replication_and_postrun()
			qc.check_values(
				share,
				quota_policy["inodeSoftLimit"],
				quota_policy["inodeHardLimit"],
				quota_policy["spaceSoftLimit"],
				quota_policy["spaceHardLimit"],
				quota_policy["reapplyQuota"]
			)
			print("Simulate login")
			self.touch_file(tfs.mount_point)
			print("Remove quota policy")
			udm.modify_object("shares/share", dn=share, policy_dereference=policy)
			utils.wait_for_replication_and_postrun()
			print("Simulate login")
			self.touch_file(tfs.mount_point)
			self._check_quota_settings(tfs.loop_dev, expected_result)

	def test_two_shares_on_one_mount(self, quota_policies, expected_result):
		with TempFilesystem(self.quota_type, fs_type=self.fs_type) as tfs, udm_test.UCSTestUDM() as udm:
			self._activate_quota(tfs.loop_dev)
			print("Create Shares")

			share1_path = os.path.join(tfs.mount_point, self.share_name)
			share2_path = os.path.join(tfs.mount_point, self.share_name2)
			os.mkdir(share1_path)
			os.mkdir(share2_path)

			share1 = udm.create_object(
				'shares/share', name=self.share_name, path=share1_path, host=self.my_fqdn, directorymode="0777"
			)
			share2 = udm.create_object(
				'shares/share', name=self.share_name2, path=share2_path, host=self.my_fqdn, directorymode="0777"
			)
			utils.wait_for_replication_and_postrun()
			qc.cache_must_exists(share1)
			qc.cache_must_exists(share2)
			print("Create user")
			udm.create_user(username=self.username, check_for_drs_replication=False)
			print("Create quota policies")
			policies = []
			for quota_policy in quota_policies:
				policies.append(self.create_quota_policy(udm, quota_policy))
			print("Append quota policies")
			udm.modify_object("shares/share", dn=share1, policy_reference=policies[0])
			udm.modify_object("shares/share", dn=share2, policy_reference=policies[1])
			utils.wait_for_replication_and_postrun()
			self.touch_file(tfs.mount_point)
			self._check_quota_settings(tfs.loop_dev, expected_result)

	def test_two_shares_on_one_mount_only_one_policy(self):
		with TempFilesystem(self.quota_type, fs_type=self.fs_type) as tfs, udm_test.UCSTestUDM() as udm:
			quota_policy = {
				"inodeSoftLimit": '10',
				"inodeHardLimit": '15',
				"spaceSoftLimit": str(1024 ** 2),
				"spaceHardLimit": str(2048 ** 2),
				"reapplyQuota": 'TRUE',
				"name": uts.random_name(),
			}

			self._activate_quota(tfs.loop_dev)
			print("Create Shares")

			share1_path = os.path.join(tfs.mount_point, self.share_name)
			share2_path = os.path.join(tfs.mount_point, self.share_name2)
			os.mkdir(share1_path)
			os.mkdir(share2_path)

			share1 = udm.create_object(
				'shares/share', name=self.share_name, path=share1_path, host=self.my_fqdn, directorymode="0777"
			)
			share2 = udm.create_object(
				'shares/share', name=self.share_name2, path=share2_path, host=self.my_fqdn, directorymode="0777"
			)
			utils.wait_for_replication_and_postrun()
			qc.cache_must_exists(share1)
			qc.cache_must_exists(share2)
			print("Create user")
			udm.create_user(username=self.username, check_for_drs_replication=False)
			print("Create quota policy")
			policy = self.create_quota_policy(udm, quota_policy)
			print("Append quota policy")
			udm.modify_object("shares/share", dn=share1, policy_reference=policy)
			utils.wait_for_replication_and_postrun()
			self.touch_file(tfs.mount_point)
			self._check_quota_settings(tfs.loop_dev)

	def touch_file(self, mountpoint):
		print("Write file on filesystem as user: {}".format(self.username))
		subprocess.check_call([
			"sudo",
			"--user",
			self.username,
			"touch",
			os.path.join(mountpoint, "foo"),
		])

	def create_quota_policy(self, udm, quota_policy):
		return udm.create_object(
			'policies/share_userquota',
			position='cn=userquota,cn=shares,cn=policies,%s' % self.ldap_base,
			name=quota_policy["name"],
			softLimitSpace=quota_policy["spaceSoftLimit"],
			hardLimitSpace=quota_policy["spaceHardLimit"],
			softLimitInodes=quota_policy["inodeSoftLimit"],
			hardLimitInodes=quota_policy["inodeHardLimit"],
			reapplyeverylogin=quota_policy["reapplyQuota"],
		)
Exemple #4
0
class User(Person):
	"""Contains the needed functuality for users in the UMC module schoolwizards/users.\n
	:param school: school name of the user
	:type school: str
	:param role: role of the user
	:type role: str ['student', 'teacher', 'staff', 'teacherAndStaff']
	:param school_classes: dictionary of school -> list of names of the class which contain the user
	:type school_classes: dict
	"""

	def __init__(self, school, role, school_classes, mode='A', username=None, firstname=None, lastname=None, password=None, mail=None, schools=None):
		super(User, self).__init__(school, role)

		if username:
			self.username = username
			self.dn = self.make_dn()
		if firstname:
			self.firstname = firstname
		if lastname:
			self.lastname = lastname
		if mail:
			self.mail = mail
		if school_classes:
			self.school_classes = school_classes
		self.schools = schools or [self.school]
		self.typ = 'teachersAndStaff' if self.role == 'teacher_staff' else self.role
		self.mode = mode

		utils.wait_for_replication()
		self.ucr = ucr_test.UCSTestConfigRegistry()
		self.ucr.load()
		host = self.ucr.get('ldap/master')
		self.client = Client(host)
		account = utils.UCSTestDomainAdminCredentials()
		admin = account.username
		passwd = account.bindpw
		self.password = password if password else passwd
		self.client.authenticate(admin, passwd)

	def append_random_groups(self):
		pass

	def __enter__(self):
		return self

	def __exit__(self, type, value, trace_back):
		self.ucr.revert_to_original_registry()

	def create(self):
		"""Creates object user"""
		flavor = 'schoolwizards/users'
		param = [{
			'object': {
				'school': self.school,
				'schools': self.schools,
				'school_classes': self.school_classes,
				'email': self.mail,
				'name': self.username,
				'type': self.typ,
				'firstname': self.firstname,
				'lastname': self.lastname,
				'password': self.password
			},
			'options': None
		}]
		print '#### Creating user %s' % (self.username,)
		print '#### param = %s' % (param,)
		reqResult = self.client.umc_command('schoolwizards/users/add', param, flavor).result
		if not reqResult[0]:
			raise CreateFail('Unable to create user (%r)' % (param,))
		else:
			utils.wait_for_replication()

	def get(self):
		"""Get user"""
		flavor = 'schoolwizards/users'
		param = [{
			'object': {
				'$dn$': self.dn,
				'school': self.school
			}
		}]
		try:
			reqResult = self.client.umc_command('schoolwizards/users/get', param, flavor).result
		except BadRequest as exc:
			if exc.status == 400:
				reqResult = ['']
			else:
				raise
		if not reqResult[0]:
			raise GetFail('Unable to get user (%s)' % self.username)
		else:
			return reqResult[0]

	def check_get(self, expected_attrs={}):
		info = {
			'$dn$': self.dn,
			'display_name': ' '.join([self.firstname, self.lastname]),
			'name': self.username,
			'firstname': self.firstname,
			'lastname': self.lastname,
			'type_name': self.type_name(),
			'school': self.school,
			'schools': set(self.schools),
			'disabled': 'none',
			'birthday': None,
			'password': None,
			'type': self.typ,
			'email': self.mail,
			'objectType': 'users/user',
			'school_classes': {},
		}
		if self.is_student() or self.is_teacher() or self.is_teacher_staff():
			info.update({'school_classes': self.school_classes})

		if expected_attrs:
			info.update(expected_attrs)

		get_result = self.get()
		# Type_name is only used for display, Ignored
		info['type_name'] = get_result['type_name']
		# ignore OU order
		get_result['schools'] = set(get_result['schools'])
		if get_result != info:
			diff = []
			for key in (set(get_result.keys()) | set(info.keys())):
				if get_result.get(key) != info.get(key):
					diff.append('%s: Got:\n%r; expected:\n%r' % (key, get_result.get(key), info.get(key)))
			raise GetCheckFail('Failed get request for user %s:\n%s' % (self.username, '\n'.join(diff)))

	def type_name(self):
		if self.typ == 'student':
			return 'Student'
		elif self.typ == 'teacher':
			return 'Teacher'
		elif self.typ == 'staff':
			return 'Staff'
		elif self.typ == 'teacherAndStaff':
			return 'Teacher and Staff'

	def query(self):
		"""get the list of existing users in the school"""
		flavor = 'schoolwizards/users'
		param = {
			'school': self.school,
			'type': 'all',
			'filter': ""
		}
		reqResult = self.client.umc_command('schoolwizards/users/query', param, flavor).result
		return reqResult

	def check_query(self, users_dn):
		q = self.query()
		k = [x['$dn$'] for x in q]
		if not set(users_dn).issubset(set(k)):
			raise QueryCheckFail('users from query do not contain the existing users, found (%r), expected (%r)' % (
				k, users_dn))

	def remove(self, remove_from_school=None):
		"""Remove user"""
		remove_from_school = remove_from_school or self.school
		print('#### Removing User %r (%s) from school %r.' % (self.username, self.dn, remove_from_school))
		flavor = 'schoolwizards/users'
		param = [{
			'object': {
				'remove_from_school': remove_from_school,
				'$dn$': self.dn,
			},
			'options': None
		}]
		reqResult = self.client.umc_command('schoolwizards/users/remove', param, flavor).result
		if not reqResult[0]:
			raise RemoveFail('Unable to remove user (%s)' % self.username)
		else:
			schools = self.schools[:]
			schools.remove(remove_from_school)
			if not schools:
				self.set_mode_to_delete()
			else:
				self.update(school=sorted(schools)[0], schools=schools, mode='M')
				try:
					del self.school_classes[remove_from_school]
				except KeyError:
					pass

	def edit(self, new_attributes):
		"""Edit object user"""
		flavor = 'schoolwizards/users'
		object_props = {
			'school': self.school,
			'schools': self.schools,
			'email': new_attributes.get('email') if new_attributes.get('email') else self.mail,
			'name': self.username,
			'type': self.typ,
			'firstname': new_attributes.get('firstname') if new_attributes.get('firstname') else self.firstname,
			'lastname': new_attributes.get('lastname') if new_attributes.get('lastname') else self.lastname,
			'password': new_attributes.get('password') if new_attributes.get('password') else self.password,
			'$dn$': self.dn,
		}
		if self.typ not in ('teacher', 'staff', 'teacherAndStaff'):
			object_props['school_classes'] = new_attributes.get('school_classes', self.school_classes)

		param = [{
			'object': object_props,
			'options': None
		}]
		print '#### Editing user %s' % (self.username,)
		print '#### param = %s' % (param,)
		reqResult = self.client.umc_command('schoolwizards/users/put', param, flavor).result
		if not reqResult[0]:
			raise EditFail('Unable to edit user (%s) with the parameters (%r)' % (self.username, param))
		else:
			self.set_mode_to_modify()
			self.school_classes = new_attributes.get('school_classes', self.school_classes)
			self.mail = new_attributes.get('email') if new_attributes.get('email') else self.mail
			self.firstname = new_attributes.get('firstname') if new_attributes.get('firstname') else self.firstname
			self.lastname = new_attributes.get('lastname') if new_attributes.get('lastname') else self.lastname
			self.password = new_attributes.get('password') if new_attributes.get('password') else self.password
Exemple #5
0
class Distribution(object):
    """Contains the needed functionality for Materials distribution.
	By default the distribution is manual.\n
	:param school: name of the ou
	:type school: str
	:param connection:
	:type connection: UMC connection object
	:param ucr:
	:type ucr: UCR object
	:param name: name of distribution project to be added later
	:type name: str
	:param description: description of distribution project to be added  later
	:type description: str
	:param sender: name of the creater user (teacher or admin)
	:type sender: str
	:param flavor: flavor of the acting user
	:type flavor: str ('teacher' or 'admin')
	:param distributeTime: time for automatic distribution
	:type distributeTime: str ('%I:%M')
	:param distributionDate: date for automatic distribution
	:type distributionDate: str ('%Y-%m-%d)
	:param collectionTime: time for automatic collection
	:type collectionTime: str ('%I:%M')
	:param collectionDate: date for automatic collection
	:type collectionDate: str ('%Y-%m-%d)
	:param distributeType: type of the distribution
	:type distributionType: str ('automatic' or 'manual')
	:param collectionTye: type of the collection
	:type collectionType: str ('automatic' or 'manual')
	:param files: names of material files for the distribution project
	:type files: list of str
	:param recipients: groups which are included in the distribution project
	:type recipients: list of group objects
	"""
    def __init__(self,
                 school,
                 connection=None,
                 sender=None,
                 flavor=None,
                 ucr=None,
                 description=None,
                 name=None,
                 distributeType='manual',
                 distributeTime=None,
                 distributeDate=None,
                 collectType='manual',
                 collectTime=None,
                 collectDate=None,
                 files=[],
                 recipients=[]):
        account = utils.UCSTestDomainAdminCredentials()
        admin = account.username
        passwd = account.bindpw
        self.school = school
        self.name = name if name else uts.random_string()
        self.description = description if description else uts.random_string()
        if distributeTime:
            self.distributeTime = distributeTime
        else:
            self.distributeTime = time.strftime('%I:%M')
        if distributeDate:
            self.distributeDate = distributeDate
        else:
            self.distributeDate = time.strftime('%Y-%m-%d')
        self.collectTime = collectTime if collectTime else time.strftime(
            '%I:%M')
        self.collectDate = collectDate if collectDate else time.strftime(
            '%Y-%m-%d')
        self.distributeType = distributeType
        self.collectType = collectType
        self.files = files
        self.recipients = recipients
        self.ucr = ucr if ucr else ucr_test.UCSTestConfigRegistry()
        self.sender = sender if sender else admin
        self.flavor = flavor if flavor else 'admin'
        if connection:
            self.client = connection
        else:
            self.client = Client(None, admin, passwd)

    def query(self, filt='private', pattern=''):
        """Calles 'distribution/query'
		:param pattern: the pattern to use in the search
		:type pattern: str
		"""
        flavor = self.flavor
        param = {'filter': filt, 'pattern': pattern}
        reqResult = self.client.umc_command('distribution/query', param,
                                            flavor).result
        result = [x['name'] for x in reqResult if reqResult is not None]
        return result

    def get(self):
        """Calls 'distribute/get'"""
        name = [self.name]
        reqResult = self.client.umc_command('distribution/get', name,
                                            self.flavor).result
        return reqResult[0]

    def idir(self, path):
        """Dir a specific path.\n
		:param path: wanted path
		:type path: str
		:return: list of file names
		"""
        files = []
        for root, _, filenames in os.walk(path):
            for f in filenames:
                files.append(os.path.relpath(os.path.join(root, f), path))
        return files

    def genData(self, file_name, content_type, boundary, flavor):
        """Generates data in the form to be sent via http POST request.\n
		:param file_name: file name to be uploaded
		:type file_name: str
		:param content_type: type of the content of the file
		:type content_type: str ('text/plain',..)
		:param boundary: the boundary
		:type boundary: str (-------123091)
		:param flavor: flavor of the acting user
		:type flavor: str
		"""
        with open(file_name, 'r') as f:
            data = r"""--{0}
Content-Disposition: form-data; name="uploadedfile"; filename="{1}"
Content-Type: {2}

{3}
--{0}
Content-Disposition: form-data; name="flavor"

{4}
--{0}
Content-Disposition: form-data; name="iframe"

false
--{0}
Content-Disposition: form-data; name="uploadType"

html5
--{0}--
""".format(boundary, file_name, content_type, f.read(), flavor)
        return data.replace("\n", "\r\n")

    def uploadFile(self, file_name, content_type):
        """Uploads a file via http POST request.\n
		:param file_name: file name to be uploaded
		:type file_name: str
		:param content_type: type of the content of the file
		:type content_type: str ('text/plain',..)
		"""
        print 'Uploading a file'
        boundary = '---------------------------103454444410473823401882756'
        data = self.genData(file_name, content_type, boundary, self.flavor)
        header_content = {
            'Content-Type': 'multipart/form-data; boundary=%s' % (boundary, )
        }
        self.client.request('POST',
                            'upload/distribution/upload',
                            data,
                            headers=header_content).result

    def add(self):
        """Create files and upload them then add the project,
		calls: 'distribution/add'
		"""
        # creatng and uploading the files
        content_type = 'text/plain'
        for filename, encoding in self.files:
            with open(filename, 'w') as g:
                g.write('test_content')
            self.uploadFile(filename, content_type)
        print 'Adding Project %s' % (self.name)
        flavor = self.flavor
        recipients = []
        for item in self.recipients:
            recipients.append(item.dn())
        print 'recipients=', recipients
        files = [
            file_name.decode(encoding).encode('UTF-8')
            for file_name, encoding in self.files
        ]
        param = [{
            'object': {
                'collectDate': self.collectDate,
                'collectTime': self.collectTime,
                'collectType': self.collectType,
                'description': self.description,
                'distributeDate': self.distributeDate,
                'distributeTime': self.distributeTime,
                'distributeType': self.distributeType,
                'files': files,
                'name': self.name,
                'recipients': recipients
            },
            'options': None
        }]
        print 'param=', param
        reqResult = self.client.umc_command('distribution/add', param,
                                            flavor).result
        print 'reqResult =', reqResult
        if not reqResult[0]['success']:
            utils.fail('Unable to add project (%r)' % (param, ))

    def check_add(self):
        """Calls 'distribution/query'
		and check the existance of the added project
		"""
        print 'Checking %s addition' % (self.name, )
        current = self.query(pattern=self.name)
        if not (self.name in current):
            utils.fail('Project %s was not added successfully' % (self.name, ))

    def put(self,
            description=None,
            distributeType=None,
            distributeTime=None,
            distributeDate=None,
            collectType=None,
            collectTime=None,
            collectDate=None,
            files=[],
            recipients=[]):
        """Modifies the already existing project.\n
		:param description: description of the project to be added later
		:type description: str
		:param distributeTime: time for automatic distribution
		:type distributeTime: str ('%I:%M')
		:param distributionDate: date for automatic distribution
		:type distributionDate: str ('%Y-%m-%d)
		:param collectionTime: time for automatic collection
		:type collectionTime: str ('%I:%M')
		:param collectionDate: date for automatic collection
		:type collectionDate: str ('%Y-%m-%d)
		:param distributeType: type of the distribution
		:type distributionType: str ('automatic' or 'manual')
		:param collectionTye: type of the collection
		:type collectionType: str ('automatic' or 'manual')
		:param files: names of material files for the distribution project
		:type files: list of str
		:param recipients: groups which are included in the project
		:type recipients: list of group objects
		"""
        print 'Editing Project %s' % (self.name)
        description = description if description else self.description
        if distributeType:
            distributeType = distributeType
        else:
            distributeType = self.distributeType
        if distributeTime:
            distributeTime = distributeTime
        else:
            distributeTime = self.distributeTime
        if distributeDate:
            distributeDate = distributeDate
        else:
            distributeDate = self.distributeDate
        collectType = collectType if collectType else self.collectType
        collectTime = collectTime if collectTime else self.collectTime
        collectDate = collectDate if collectDate else self.collectDate
        files = files if files else [x for x, y in self.files]
        recipients = recipients if recipients else self.recipients
        new_recipients = []
        for item in recipients:
            new_recipients.append(item.dn())
        flavor = self.flavor
        param = [{
            'object': {
                'collectDate': collectDate,
                'collectTime': collectTime,
                'collectType': collectType,
                'description': description,
                'distributeDate': distributeDate,
                'distributeTime': distributeTime,
                'distributeType': distributeType,
                'files': files,
                'name': self.name,
                'recipients': new_recipients
            },
            'options': None
        }]
        reqResult = self.client.umc_command('distribution/put', param,
                                            flavor).result
        print 'reqResult =', reqResult
        if not reqResult[0]['success']:
            utils.fail('Unable to edit project with params =(%r)' % (param, ))
        else:
            self.description = description
            self.distributeType = distributeType
            self.distributeTime = distributeTime
            self.distributeDate = distributeDate
            self.collectType = collectType
            self.collectTime = collectTime
            self.collectDate = collectDate
            self.files = [(x, 'utf8') for x in files]
            self.recipients = recipients

    def check_put(self, previousGetResult):
        """Calls 'distribution/get' and check the modified project
		:param previousGetResult: info from previous get
		:type previousGetResult: dict
		check changing sates for distribution and collection
		"""
        print 'Checking %s modification' % (self.name, )
        found = self.get()
        supposed = {
            'files': found['files'],
            'sender': found['sender'],
            'description': found['description'],
            'recipients': found['recipients'],
            'distributeType': found['distributeType'],
            '__type__': found['__type__'],
            'collectType': found['collectType'],
            'name': found['name'],
            'starttime': found['starttime'],
            'deadline': found['deadline']
        }
        recips = [{'id': y.dn(), 'label': y.name} for y in self.recipients]

        if self.distributeType != 'automatic':
            sTime = None
        else:
            sTime = '%s %s' % (self.distributeDate, self.distributeTime)
        if self.collectType != 'automatic':
            dTime = None
        else:
            dTime = '%s %s' % (self.collectDate, self.collectTime)
        current = {
            'files': [x for x, y in self.files],
            'sender': self.sender,
            'description': self.description,
            'recipients': recips,
            'distributeType': self.distributeType,
            '__type__': 'PROJECT',
            'collectType': self.collectType,
            'name': self.name,
            'starttime': sTime,
            'deadline': dTime,
        }
        print 'supposed = ', supposed
        print 'current = ', current

        fail_state = supposed != current
        if fail_state:
            utils.fail(
                'Project %s was not modified successfully,supposed!=current' %
                (self.name, ))

        # check distribute
        check = 'distribution'
        before_type = previousGetResult['distributeType']
        after_type = found['distributeType']
        before_time = previousGetResult['starttime']
        after_time = found['starttime']
        before_atJob = previousGetResult['atJobNumDistribute']
        after_atJob = found['atJobNumDistribute']
        fail_state = fail_state or self.put_fail(
            before_type, after_type, before_time, after_time, before_atJob,
            after_atJob)
        if fail_state:
            utils.fail(
                'Project %s was not modified successfully, %s: %s -> %s' %
                (self.name, check, before_type, after_type))

        # check collect
        check = 'collection'
        before_type = previousGetResult['collectType']
        after_type = found['collectType']
        before_time = previousGetResult['deadline']
        after_time = found['deadline']
        before_atJob = previousGetResult['atJobNumCollect']
        after_atJob = found['atJobNumCollect']
        fail_state = fail_state or self.put_fail(
            before_type, after_type, before_time, after_time, before_atJob,
            after_atJob)
        if fail_state:
            utils.fail(
                'Project %s was not modified successfully, %s: %s -> %s' %
                (self.name, check, before_type, after_type))

    def put_fail(self, before_type, after_type, before_time, after_time,
                 before_atJob, after_atJob):
        """Checks if the atjobs are in the expected formats
		:param before_type: type before using put command
		:type before_type: str
		:param after_type: type after using put command
		:type after_type: str
		:param before_atJob: atJobNum before using put command
		:type before_atJob: str or None
		:param after_atJob: atJobNum after using put command
		:type after_atJob: str or None
		:param before_time: time before using put command
		:type before_time: str
		:param after_time: time after using put command
		:type after_time: str
		"""
        fail_state = False
        # manual -> manual
        # atJobs == don't care
        if before_type == 'manual' and after_type == 'manual':
            pass

        # manual -> automatic
        # atJobs don't care -> int
        if before_type == 'manual' and after_type == 'automatic':
            fail_state = not (isinstance(after_atJob, (int, long)))

        # automatic -> manual
        # atJobs int -> don't care
        if before_type == 'automatic' and after_type == 'manual':
            fail_state = not (isinstance(before_atJob, (int, long)))

        # automatic -> automatic
        # atJobs int1 -> int2 & int1 < int2
        if before_type == 'automatic' and after_type == 'automatic':
            fail1 = not (isinstance(before_atJob, (int, long))
                         and isinstance(after_atJob, (int, long)))
            fail2 = not (before_time != after_time and
                         (before_atJob < after_atJob))
            fail_state = fail1 or fail2
        return fail_state

    def distribute(self):
        """Calls 'distribution/distribute'"""
        print 'Distributing Project %s' % (self.name)
        flavor = self.flavor
        reqResult = self.client.umc_command('distribution/distribute',
                                            [self.name], flavor).result
        if not reqResult[0]['success']:
            utils.fail('Unable to distribute project (%r)' % (self.name, ))

    def check_distribute(self, users):
        """Checks if the distribution was successful
		by checking the file system.\n
		:param users: names of users to have the material distributed for
		:type users: list of str
		"""
        print 'Checking %s distribution' % (self.name, )
        for user in users:
            path = self.getUserFilesPath(user, 'distribute')
            print 'file_path=', path
            existingFiles = self.idir(path)
            print 'existingFiles=', existingFiles
            files = [x for x, y in self.files]
            if files != existingFiles:
                utils.fail('Project files were not distributed for user %s' %
                           (user, ))

    def collect(self):
        """Calls 'distribution/collect'"""
        print 'Collecting Project %s' % (self.name)
        flavor = self.flavor
        reqResult = self.client.umc_command('distribution/collect',
                                            [self.name], flavor).result
        if not reqResult[0]['success']:
            utils.fail('Unable to collect project (%r)' % (self.name, ))

    def check_collect(self, users):
        """Checks if the collection was successful
		by checking the file system.\n
		:param users: names of users to have the material collected form
		:type users: list of str
		"""
        print 'Checking %s collection' % (self.name, )
        for user in users:
            path = self.getUserFilesPath(user, 'collect')
            print 'file_path=', path
            existingFiles = self.idir(path)
            print 'existingFiles=', existingFiles
            files = [x for x, y in self.files]
            if files != existingFiles:
                utils.fail('Project files were not collected for user %s' %
                           (user, ))

    def remove(self):
        """Calls 'distribution/remove'"""
        print 'Removing Project %s' % (self.name)
        flavor = self.flavor
        param = [{'object': self.name, 'options': None}]
        reqResult = self.client.umc_command('distribution/remove', param,
                                            flavor).result
        if reqResult:
            utils.fail('Unable to remove project (%r)' % (param, ))

    def check_remove(self):
        """Calls 'distribution/query'
		and check the existance of the removed project
		"""
        print 'Checking %s removal' % (self.name, )
        current = self.query(pattern=self.name)
        if self.name in current:
            utils.fail('Project %s was not removed successfully' %
                       (self.name, ))

    def checkFiles(self, files):
        """Calls 'distribution/checkfiles'"""
        print 'Checking files Project %s' % (self.name)
        flavor = self.flavor
        param = {'project': self.name, 'filenames': files}
        reqResult = self.client.umc_command('distribution/checkfiles', param,
                                            flavor).result
        if reqResult:
            utils.fail('Unable to chack files for project (%r)' % (param, ))

    def adopt(self, project_name):
        """Calls 'distribute/adopt'"""
        print 'Adopting project', self.name
        flavor = self.flavor
        reqResult = self.client.umc_command('distribution/adopt',
                                            [project_name], flavor).result
        if reqResult:
            utils.fail('Failed to adopt project (%r)' % (project_name, ))

    def check_adopt(self, project_name):
        print 'Checking adopting'
        q = self.query(pattern=project_name)
        if not (project_name in q):
            utils.fail('Project %s was not adopted successfully' %
                       (project_name, ))

    def getUserFilesPath(self, user, purpose='distribute'):
        """Gets the correct files path for a specific user depending on
		the value of the ucr variable ucsschool/import/roleshare.\n
		:param user: user name
		:type user: str
		:param purpose: either for distribution or collection
		:type purpose: str ('distribute' or 'collect')
		"""
        path = ''
        self.ucr.load()
        roleshare = self.ucr.get('ucsschool/import/roleshare')
        sender_dir_name = self.ucr.get(
            'ucsschool/datadistribution/datadir/sender', 'Unterrichtsmaterial')
        project_dir_suffix = self.ucr.get(
            'ucsschool/datadistribution/datadir/sender/project/suffix',
            '-Ergebnisse')
        recipient_dir_name = self.ucr.get(
            'ucsschool/datadistribution/datadir/recipient',
            'Unterrichtsmaterial')
        if purpose == 'distribute':
            if roleshare == 'no' or roleshare is False:
                path = '/home/{0}/{1}/{2}/'.format(user, recipient_dir_name,
                                                   self.name)
            else:
                path = '/home/{0}/schueler/{1}/{2}/{3}'.format(
                    self.school, user, recipient_dir_name, self.name)
        elif purpose == 'collect':
            if roleshare == 'no' or roleshare is False:
                path = '/home/{0}/{1}/{2}{3}/{4}/'.format(
                    self.sender, sender_dir_suffix, self.name,
                    project_dir_name, user)
            else:
                path = '/home/{0}/lehrer/{1}/{2}/{3}{4}/{5}'.format(
                    self.school, self.sender, sender_dir_name, self.name,
                    project_dir_suffix, user)
        return path
Exemple #6
0
class CSVImport(object):
    """CSVImport class, inclues all the needed operations to perform a user import"""
    def __init__(self, school, user_type):
        self.school = school
        self.user_type = user_type
        self.ucr = ucr_test.UCSTestConfigRegistry()
        self.ucr.load()
        host = self.ucr.get('hostname')
        self.client = Client(host)
        account = utils.UCSTestDomainAdminCredentials()
        admin = account.username
        passwd = account.bindpw
        self.client.authenticate(admin, passwd)

    def genData(self, boundary, file_name, content_type, school, user_type,
                delete_not_mentioned):
        """Generates data in the form to be sent via http POST request.\n
		:param file_name: file name to be uploaded
		:type file_name: str
		:param content_type: type of the content of the file
		:type content_type: str  = 'text/csv'
		:param boundary: the boundary
		:type boundary: str (-------123091)
		:param flavor: flavor of the acting user
		:type flavor: str
		"""
        with open(file_name, 'r') as f:
            if delete_not_mentioned:
                data = r"""--{0}
Content-Disposition: form-data; name="uploadedfile"; filename="{1}"
Content-Type: {2}

{3}
--{0}
Content-Disposition: form-data; name="school"

{4}
--{0}
Content-Disposition: form-data; name="type"

{5}
--{0}
Content-Disposition: form-data; name="delete_not_mentioned"

true
--{0}
Content-Disposition: form-data; name="iframe"

false
--{0}
Content-Disposition: form-data; name="uploadType"

html5
--{0}--
""".format(boundary, file_name, content_type, f.read(), school, user_type)
            else:
                data = r"""--{0}
Content-Disposition: form-data; name="uploadedfile"; filename="{1}"
Content-Type: {2}

{3}
--{0}
Content-Disposition: form-data; name="school"

{4}
--{0}
Content-Disposition: form-data; name="type"

{5}
--{0}
Content-Disposition: form-data; name="iframe"

false
--{0}
Content-Disposition: form-data; name="uploadType"

html5
--{0}--
""".format(boundary, file_name, content_type, f.read(), school, user_type)
        return data.replace("\n", "\r\n")

    def uploadFile(self, file_name, content_type, delete_not_mentioned,
                   expected_upload_status):
        """Uploads a file via http POST request.\n
		:param file_name: file name to be uploaded
		:type file_name: str
		:param content_type: type of the content of the file
		:type content_type: str ('text/csv')
		"""
        print 'Uploading file %r' % file_name
        boundary = '---------------------------18209455381072592677374099768'
        data = self.genData(boundary, file_name, content_type, self.school,
                            self.user_type, delete_not_mentioned)

        header_content = {
            'Content-Type': 'multipart/form-data; boundary=%s' % (boundary, )
        }

        try:
            response = self.client.request('POST',
                                           'upload/schoolcsvimport/save',
                                           data,
                                           headers=header_content)
        except HTTPError as exc:
            response = exc.response
        status = response.status
        if status != expected_upload_status:
            raise FailHTTPStatus('Unexpected response status=%r' % status)
        elif status == 200:
            self.file_id = response.result[0]['file_id']
            self.id_nr = 1
        else:
            print 'Expected http_status = %r' % status
        return status

    def show(self):
        param = {
            'file_id':
            self.file_id,
            'columns': [
                "name", "firstname", "lastname", "birthday", "password",
                "email", "school_classes"
            ],
        }
        if self.user_type == 'staff':
            param['columns'].remove('school_classes')
        try:
            reqResult = self.client.umc_command('schoolcsvimport/show',
                                                param).result
            self.id_nr = reqResult['id']
        except FailShow:
            raise

    def progress(self):
        param = {'progress_id': self.id_nr}
        try:
            reqResult = self.client.umc_command('schoolcsvimport/progress',
                                                param).result
        except FailProgress:
            raise
        return reqResult

    def recheck(self, user):
        param = {'file_id': self.file_id, 'user_attrs': [user]}
        try:
            reqResult = self.client.umc_command('schoolcsvimport/recheck',
                                                param).result
            print 'RECHECK RESULT = ', reqResult
            return reqResult
        except FailRecheck:
            raise

    def schools(self):
        try:
            reqResult = self.client.umc_command('schoolcsvimport/schools',
                                                {}).result
        except FailSchools:
            raise
        return [x['id'] for x in reqResult]

    def check_schools(self):
        if self.school not in self.schools():
            raise FailSchools(
                'School %s not found by request: schoolcsvimport/schools' %
                (self.school))

    def write_import_file(self, filename, lines, has_header=True):
        with open(filename, 'wb') as f:
            f.write(''.join(lines))
            f.flush()

    def read_import_file(self, filename, has_header=True):
        with open(filename, 'rb') as f:
            lines = f.readlines()
        if has_header:
            columns = lines[0][:-1].split(',')
            lines = lines[1:]
        else:
            columns = []
        lines = [x[:-1] for x in lines]
        return lines, columns

    def import_users(self, users):
        line_nr = 1
        param = []

        def get_type_name(typ):
            if typ == 'cSVStudent':
                return 'Student'
            elif typ == 'cSVTeacher':
                return 'Teacher'
            elif typ == 'cSVStaff':
                return 'Staff'
            elif typ == 'cSVTeachersAndStaff':
                return 'Teacher and Staff'

        for user in users:
            user.update({'line': line_nr})
            user.update({'type_name': get_type_name(user['type'])})
            options = {'file_id': self.file_id, 'attrs': user}
            line_nr += 1
            param.append(options)
        try:
            pprint(('Importing users with parameters=', param))
            reqResult = self.client.umc_command('schoolcsvimport/import',
                                                param).result
            self.id_nr = reqResult['id']
            utils.wait_for_replication()
        except FailImport:
            raise
Exemple #7
0
class QuoataCheck(object):
    def __init__(self, quota_type="usrquota", fs_type="ext4"):
        ucr = ucr_test.UCSTestConfigRegistry()
        ucr.load()
        self.my_fqdn = '%s.%s' % (ucr.get('hostname'), ucr.get('domainname'))
        account = utils.UCSTestDomainAdminCredentials()
        self.umc_client = Client(self.my_fqdn,
                                 username=account.username,
                                 password=account.bindpw)
        self.share_name = uts.random_name()
        self.username = uts.random_name()
        self.quota_type = quota_type
        self.fs_type = fs_type
        self.quota_policy = {
            "inodeSoftLimit":
            '10',
            "inodeHardLimit":
            '15',
            "spaceSoftLimit":
            str(1024**2),
            "spaceHardLimit":
            str(2048**2),
            "reapplyQuota":
            'TRUE',
            "name":
            uts.random_name(),
            "position":
            'cn=userquota,cn=shares,cn=policies,%s' % ucr.get('ldap/base'),
        }

    def _activate_quota(self, loop_dev):
        print("Enable quota")
        options = {"partitionDevice": loop_dev}
        result = self.umc_client.umc_command('quota/partitions/activate',
                                             options).result
        if not result.get('success'):
            utils.fail("Activating quota failed:\n{}".format(result))

    def _check_quota_settings(self, loop_dev):
        print("Check quota settings")
        options = {"filter": "*", "partitionDevice": loop_dev}
        user_quotas = self.umc_client.umc_command('quota/users/query',
                                                  options).result
        expected_user_quota = {
            u'fileLimitHard': u'15',
            u'fileLimitSoft': u'10',
            u'fileLimitTime': u'-',
            u'fileLimitUsed': u'1',
            u'id': u'{}@{}'.format(self.username, loop_dev),
            u'partitionDevice': u'{}'.format(loop_dev),
            u'sizeLimitHard': float(4),
            u'sizeLimitSoft': float(1),
            u'sizeLimitTime': u'-',
            u'sizeLimitUsed': float(0),
            u'user': u'{}'.format(self.username),
        }
        if expected_user_quota not in user_quotas:
            utils.fail("Quota was not set through pam")

    def test_quota_pam(self):
        with TempFilesystem(
                self.quota_type,
                fs_type=self.fs_type) as tfs, udm_test.UCSTestUDM() as udm:
            self._activate_quota(tfs.loop_dev)
            print("Create Share")
            share = udm.create_object('shares/share',
                                      name=self.share_name,
                                      path=tfs.mount_point,
                                      host=self.my_fqdn,
                                      directorymode="0777")
            utils.wait_for_replication_and_postrun()
            qc.cache_must_exists(share)
            print("Create user")
            udm.create_user(username=self.username,
                            check_for_drs_replication=False)
            print("Create quota policy")
            policy = udm.create_object(
                'policies/share_userquota',
                position=self.quota_policy["position"],
                name=self.quota_policy["name"],
                softLimitSpace=self.quota_policy["spaceSoftLimit"],
                hardLimitSpace=self.quota_policy["spaceHardLimit"],
                softLimitInodes=self.quota_policy["inodeSoftLimit"],
                hardLimitInodes=self.quota_policy["inodeHardLimit"],
                reapplyeverylogin=self.quota_policy["reapplyQuota"],
            )
            print("Append quota policy")
            udm.modify_object("shares/share",
                              dn=share,
                              policy_reference=policy)
            utils.wait_for_replication_and_postrun()
            qc.check_values(share, self.quota_policy["inodeSoftLimit"],
                            self.quota_policy["inodeHardLimit"],
                            self.quota_policy["spaceSoftLimit"],
                            self.quota_policy["spaceHardLimit"],
                            self.quota_policy["reapplyQuota"])
            print("Write file on filesystem as user: {}".format(self.username))
            subprocess.check_call([
                "sudo",
                "--user",
                self.username,
                "touch",
                os.path.join(tfs.mount_point, "foo"),
            ])
            self._check_quota_settings(tfs.loop_dev)