Changeset 14934
- Timestamp:
- 10 Jan 2018, 14:44:49 (7 years ago)
- Location:
- main/waeup.kofa/trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/trunk/CHANGES.txt
r14915 r14934 4 4 1.6.dev0 (unreleased) 5 5 ======================= 6 7 * Do no longer hide the 'Create students' buttons but switch the portal to 8 maintenance mode to ensure that nobody can enter the portal during 9 record creation except for user 'admin'. This guarantees that record 10 creation is only started once. 6 11 7 12 * Replace `gpa_boundaries` utility attribute by `GPABoundaries` method -
main/waeup.kofa/trunk/docs/source/userdocs/applicants/create_students.rst
r14683 r14934 25 25 applicants will be skipped without further notice. 26 26 27 3. Last but not least, the portal manager with user id ``admin`` 28 does see a link button: 27 3. Last but not least, the portal managers do see a link button: 29 28 30 29 |create_students_button| … … 32 31 on the `ApplicantsContainerPage` and on the `ApplicantsRootPage` 33 32 which creates student records from applicants inside a single 34 applicants container or even portal-wide respectively. 33 applicants container or even portal-wide respectively. A warning 34 message appears before the process is started. After start the 35 portal is immediately switched into maintenance mode to ensure that 36 nobody can enter the portal during record creation except for user 37 'admin'. Maintenance mode is switched off as soon as the process has 38 finished. 35 39 36 The reader may wonder: Why only user ``admin``? 40 .. note:: 37 41 38 42 Batch creation of thousands or even tenthousands of student records 39 43 is very computation intensive and takes quite a long time, even with 40 44 powerful computers. Experience has shown that the portal must be 41 disconnected from the Internet in order to avoid database write 42 conflict errors, which cannot be resolved if also students access 43 the portal. Usually conflict errrors are not serious. Unresolved 44 conflicts just lead to an error message and the database remains 45 unchanged. Unfortunataly, student creation does not only alter the 46 object database. As we will see below, also folders and files in the 47 filesystem are added. These filesystem changes are not being 48 reverted after unresolved conflicts, a fact which can cause serious 49 problems. 50 51 So the answer to the question is trivial: We expect that the admin 52 user knows what s/he is doing and is careful enough to start the 53 creation process in maintenance mode, which means when the portal is 54 disconnected from a public network. 45 switched to maintenance mode (or even disconnected from the Internet) 46 in order to avoid database write conflict errors, which cannot be 47 resolved if also students access the portal. Usually conflict 48 errrors are not serious. Unresolved conflicts just lead to an error 49 message and the database remains unchanged. Unfortunataly, student 50 creation does not only alter the object database. As we will see 51 below, also folders and files in the filesystem are added. These 52 filesystem changes are not being reverted after unresolved conflicts, 53 a fact which can cause serious problems. 55 54 56 55 -
main/waeup.kofa/trunk/src/waeup/kofa/applicants/browser.py
r14682 r14934 24 24 from urllib import urlencode 25 25 from datetime import datetime, date 26 from time import time 26 from time import time, sleep 27 27 from zope.event import notify 28 28 from zope.component import getUtility, queryUtility, createObject, getAdapter … … 680 680 class CreateAllStudentsPage(UtilityView, grok.View): 681 681 """Create all student objects from applicant data 682 in the root container or in a specific 682 in the root container or in a specific applicants container only. 683 683 Only PortalManagers can do this. 684 684 """ … … 688 688 689 689 def update(self): 690 grok.getSite()['configuration'].maintmode_enabled_by = u'admin' 691 transaction.commit() 692 # Wait 10 seconds for all transactions to be finished. 693 # Do not wait in tests. 694 if not self.request.principal.id == 'zope.mgr': 695 sleep(10) 690 696 cat = getUtility(ICatalog, name='applicants_catalog') 691 697 results = list(cat.searchResults(state=(ADMITTED, ADMITTED))) … … 706 712 applicants_root.logger.info( 707 713 '%s - %s - %s' % (ob_class, result.applicant_id, msg)) 714 grok.getSite()['configuration'].maintmode_enabled_by = None 708 715 if len(created): 709 716 self.flash(_('${a} students successfully created.', -
main/waeup.kofa/trunk/src/waeup/kofa/applicants/tests/test_applicantcopier.py
r12565 r14934 26 26 from zope.component import getUtility 27 27 from zope.i18n import translate 28 from zope.securitypolicy.interfaces import IPrincipalRoleManager 28 29 from waeup.kofa.testing import FunctionalLayer 29 30 from waeup.kofa.interfaces import IExtFileStore, IFileStoreNameChooser … … 42 43 43 44 def prepare_applicant(self): 44 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')45 45 self.browser.open(self.manage_path) 46 46 self.fill_correct_values() … … 56 56 57 57 def test_copier(self): 58 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 58 59 self.prepare_applicant() 59 60 storage = getUtility(IExtFileStore) … … 140 141 141 142 def test_batch_copying(self): 143 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 142 144 self.prepare_applicant() 143 145 IWorkflowState(self.applicant).setState('admitted') … … 155 157 logfile = os.path.join( 156 158 self.app['datacenter'].storage, 'logs', 'applicants.log') 159 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 157 160 self.prepare_applicant() 158 161 self.browser.open(self.container_path + '/createallstudents') … … 182 185 logfile = os.path.join( 183 186 self.app['datacenter'].storage, 'logs', 'applicants.log') 187 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 184 188 self.prepare_applicant() 185 189 self.browser.open(self.manage_path) … … 238 242 logcontent = open(logfile).read() 239 243 self.assertTrue('IOError: Application Slip could not be created.' in logcontent) 244 245 def disabled_test_delay(self): 246 # Create portalmanager manager 247 self.app['users'].addUser('mrportalmanager', 'mrportalmanagersecret') 248 self.app['users']['mrportalmanager'].email = 'mrportalmanager@foo.ng' 249 self.app['users']['mrportalmanager'].title = 'Carlos Portales' 250 prmglobal = IPrincipalRoleManager(self.app) 251 prmglobal.assignRoleToPrincipal( 252 'waeup.PortalManager', 'mrportalmanager') 253 # Login as portal manager 254 self.browser.open(self.login_path) 255 self.browser.getControl(name="form.login").value = 'mrportalmanager' 256 self.browser.getControl(name="form.password").value = 'mrportalmanagersecret' 257 self.browser.getControl("Login").click() 258 self.prepare_applicant() 259 self.browser.open(self.manage_path) 260 self.browser.getControl(name="form.date_of_birth").value = '09/09/1988' 261 self.browser.getControl(name="form.course_admitted").value = ['CERT1'] 262 self.browser.getControl("Save").click() 263 IWorkflowState(self.applicant).setState('admitted') 264 notify(grok.ObjectModifiedEvent(self.applicant)) 265 start = datetime.now() 266 self.browser.open(self.root_path + '/createallstudents') 267 self.assertTrue('1 students successfully created' in self.browser.contents) 268 self.assertTrue((datetime.now() - start).seconds >= 10) -
main/waeup.kofa/trunk/src/waeup/kofa/applicants/viewlets.py
r13951 r14934 167 167 grok.order(4) 168 168 169 creation_warning = _( 170 "'The creation process may take a considerably long time " 171 "depending on the number of student records to be created " 172 "(appr. 0.5s per student). " 173 "All users will be logged out and the portal will be in " 174 "maintenance mode during record creation. You have to login again after " 175 "creation process has finished. " 176 "Do you really want to start the process now?'") 177 169 178 class ApplicantsRootCreateStudentsActionButton(ManageActionButton): 170 179 grok.order(3) … … 177 186 178 187 @property 179 def target_url(self): 180 if self.target and self.request.principal.id == 'admin': 181 return self.view.url(self.view.context, self.target) 182 return 188 def onclick(self): 189 return "return window.confirm(%s);" % creation_warning 183 190 184 191 class ApplicantsContainerCreateStudentsActionButton(ManageActionButton): … … 192 199 193 200 @property 194 def target_url(self): 195 if self.target and self.request.principal.id == 'admin': 196 return self.view.url(self.view.context, self.target) 197 return 201 def onclick(self): 202 return "return window.confirm(%s);" % creation_warning 198 203 199 204 class ApplicantViewActionButton(ManageActionButton):
Note: See TracChangeset for help on using the changeset viewer.