Segnalazione #231
import csv da errore
100%
Description
octonet 0.2.2-1
octofussd 8.0.16-1
Error in test import.csv: not imported
Row number     Field     Error
0     username     User already exists
1     username     User already exists
2     username     User already exists
3     username     User already exists
4     username     User already exists
5     username     User already exists
6     username     User already exists
7     username     User already exists
8     username     User already exists
9     username     User already exists
10     username     User already exists
11     username     User already exists
12     username     User already exists
13     username     User already exists
14     username     User already exists
15     username     User already exists
16     username     User already exists
17     username     User already exists
18     username     User already exists
19     username     User already exists
20     username     User already exists
21     username     User already exists
22     username     User already exists
23     username     User already exists
24     username     User already exists
25     username     User already exists
26     username     User already exists
27     username     User already exists
28     username     User already exists
29     username     User already exists
30     username     User already exists
31     username     User already exists
32     username     User already exists
33     username     User already exists
34     username     User already exists
35     username     User already exists
36     username     User already exists
37     username     User already exists
38     username     User already exists
39     username     User already exists
40     username     User already exists
41     username     User already exists
42     username     User already exists
43     username     User already exists
44     username     User already exists
45     username     User already exists
46     username     User already exists
47     username     User already exists
48     username     User already exists
49     username     User already exists
50     username     User already exists
51     username     User already exists
52     username     User already exists
53     username     User already exists
54     username     User already exists
55     username     User already exists
56     username     User already exists
57     username     User already exists
58     username     User already exists
59     username     User already exists
60     username     User already exists
61     username     User already exists
62     username     User already exists
63     username     User already exists
64     username     User already exists
65     username     User already exists
66     username     User already exists
67     username     User already exists
68     username     User already exists
69     username     User already exists
70     username     User already exists
71     username     User already exists
72     username     User already exists
73     username     User already exists
74     username     User already exists
75     username     User already exists
76     username     User already exists
77     username     User already exists
78     username     User already exists
79     username     User already exists
80     username     User already exists
81     username     User already exists
82     username     User already exists
83     username     User already exists
84     username     User already exists
85     username     User already exists
86     username     User already exists
87     username     User already exists
88     username     User already exists
89     username     User already exists
90     username     User already exists
91     username     User already exists
92     username     User already exists
93     username     User already exists
Files
Associated revisions
Try to solve the bug. First step: StreamingHttpResponse without redirect. refs: #231
Make use of self.imported_ok. refs: #231
Send back percentage instead of . refs: #231
Draft modal window. refs: #231
Add an id to the form. refs: #231
preventDefault and show the modal. refs: #231
Fix percentage calculation. refs: #231
Disable also closing the modal via Esc keyboard button. refs: #231
Add progress bar (static for now...). refs: #231
Add CSVImportAJAX. refs: #231
Work in progress JS code for the ajax call...Not working. refs: #231
Avoid KeyError. IS IT GOOD?. refs: #231
POST also the CSV file. refs: #231
Avoid HTTP 500 when the form does not validate. Hopefully we never land here... refs: #231
Cleanup. refs: #231
Fix the percentage. refs: #231
Try to understand when/if the onprogress event is catchable... refs: #231
Comment. refs: #231
Cleanup. refs: #231
Manage the good POST: change modal title, show button and message, get redirect to user list. refs: #231
Backend rewrite to support error handling in the new AJAX powered users' CSV import. refs: #231
Javascript frontend code to somehow show the errors if they happened in the backend, during users' CSV import. refs: #231
Empty the table prior to creating the errors' rows. refs: #231
Remove the old django template code, not used anymore. refs: #231
Message does not use the filename. refs: #231
Better error message. refs: #231
Consistent CSS ids. refs: #231
Show errors. refs: #231
Check that controller group exists, as it's done with primary group. refs: #231
Add support to form errors. refs: #231
Hide and empty all error related things on load, to avoid showing unwanted things. refs: #231
This is unused. refs: #231
Massive cleanup after AJAXizing the CSV import. refs: #231
refs #231
version bump
Try to fix backend to be more resilient AND information giving... refs: #231
JS code to take care of the frontend when there is an Exception in the backend during CSV import. refs: #231
Cleanup. refs: #231
Restore the old error management and keep the new one. Best of both worlds. refs: #231
History
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from TRUELITE to Mark Caglienzi
 
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Status changed from Nuovo to Commenti
 - Assignee changed from Mark Caglienzi to Michael Guggenberg
 
Solo per escludere l'ovvio, visto l'errore generato, quegli utenti non esistevano gia' quando hai provato la procedura di importazione?
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Subject changed from import cvs da errore to import csv da errore
 
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    Prtito da uno snapshot senza utenti
Creato grupp studenti, creato gruppo docenti.
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from Michael Guggenberg to Mark Caglienzi
 
Ok, grazie, verifichiamo.
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    la home impostata a /home/studenti/_classe_ è stata ignorata ed è stata impostata a /home/_username_
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Status changed from In elaborazione to Commenti
 - Assignee changed from Mark Caglienzi to Michael Guggenberg
 
Potete riprovare dopo aver aggiornato octofussd (8.0.17-1) e soprattutto octonet (0.2.3-1) ponendo l'attenzione su queste cose:
- Che gli utenti che si sta cercando di importare non esistano già (questo accade anche se si fa l'importazione due volte con lo stesso file CSV. La prima volta funziona correttamente, la seconda volta no)
 - Il problema degli utenti già esistenti si può presentare anche nel caso in cui siano due persone a usare l'interfaccia: la prima che fa l'import avrà l'esito positivo, la seconda che lo fa (anche un secondo dopo) avrà l'esito negativo.
 - Che le colonne siano selezionate correttamente prima di iniziare l'import (dato che l'importer cerca di fare automaticamente l'assegnamento delle colonne, ma può sbagliare)
 
- La home nei miei test in locale adesso viene importata correttamente (problema segnalato nel ticket)
 - Non veniva importato il controller group, ora invece nei miei test in locale questo viene importato correttamente
 
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    - File Screenshot - 04262017 - 05_08_13 PM.png Screenshot - 04262017 - 05_08_13 PM.png added
 - File pre_import.ldif pre_import.ldif added
 - File post_import.ldif post_import.ldif added
 - File import.csv import.csv added
 
octonet 0.2.3-1
octofussd 8.0.17-1
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Status changed from Commenti to In elaborazione
 - Assignee changed from Michael Guggenberg to Mark Caglienzi
 
Questo problema è ancora diverso, sembra che ci sia stato un import parziale degli utenti e che poi la connessione si sia interrotta/resettata per qualche motivo.
Indago.
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Status changed from In elaborazione to Commenti
 - Assignee changed from Mark Caglienzi to Christopher R. Gabriel
 
Rivoluzionato il backend dopo analisi con Simone e Christopher riguardo anche a octofussd (c'è un grosso problema sul numero delle connessioni create verso LDAP), e di conseguenza anche il frontend è cambiato.
9e271577:- Ora il POST del CSV è fatto via AJAX
 - E' stata scritta una nuova view, e quella vecchia è diventata una 
TemplateViewdato che non gestisce POST ma deve soltanto renderizzare un template, e il suo codice diform_valid()è stato usato come base per il codice dipost()della nuova view AJAX - La view di backend ovviamente inizia a creare gli utenti solo se il CSV non ha problemi (cioè se è stato configurato correttamente l'import rispetto alle colonne da importare, se gli utenti da importare non esistono, se i gruppi a cui aggiungere gli utenti esistono già, eccetera).
 - In presenza di anche un solo errore e non viene importato nessun utente, per evitare import parziali (come era già anche prima, del resto)
 - La view di backend AJAX in caso di successo invia una StreamingHttpResponse con la percentuale di utenti creati rispetto al totale degli utenti da importare
 - Se tutto è ok, l'import inizia e viene mostrata una finestra modale con alcuni messaggi (è FONDAMENTALE non chiudere la finestra modale, né la finestra del browser, finché non viene dato il messaggio di importazione effettuata, altrimenti in questo caso sì che ci saranno import parziali. Il processo può impiegare davvero molti minuti, dipendentemente dal numero di utenti importati)
 - La percentuale di completamento dell'import inviata via StreamingHttpResponse viene usata per aggiornare una barra di progresso nella finestra modale.
 - Alla fine dell'import viene mostrato, sempre nella finestra modale, un messaggio di fine processo e un bottone che rimanda alla lista utenti, dove si potrà appurare che l'import è riuscito.
 
- In caso di errori la finestra modale viene nascosta e vengono mostrati gli errori, senza un reload della pagina (ma modificando il DOM via javascript).
 - I messaggi di errore hanno la stessa forma che avevano prima
 - Prima vengono considerati gli errori di conformità del form (ad esempio non si può chiedere di importare Full Name e uno o entrambi Name e Surname), dato che questi controlli non necessitano di LDAP
 - Se il form è ok, vengono effettuati i controlli lato LDAP (gruppi non esistenti, utenti esistenti, ecc...)
 - A ogni segnalazione di errore, il form resta compilato e funzionale, in questo modo è possibile fare le correzioni e procedere all'upload rapidamente (ad esempio se l'unico errore è "Gruppo non esistente", si può aprire un secondo tab in cui si crea il gruppo, poi tornare al tab dell'upload e premere Upload senza dover rifare tutta la procedura di selezione file e ordinamento colonne)
 
Nel frattempo sono state aggiunte alcune cose (ad esempio il controllo dell'esistenza del gruppo controller, che prima non veniva effettuato esplicitamente), e corretti alcuni particolari qua e là (typo, eccetera)
Codice pushato nel branch t231 e NON mergiato in master.
Io ho modificato il codice di octonet, il cui pacchetto quindi è da rifare.
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from Christopher R. Gabriel to Michael Guggenberg
 
Uploadati i pacchetti
- octofussd 8.0.19
 - octonet 0.2.5
 
che includono tutto il fix della procedura di importazione.
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    - File import_1.csv import_1.csv added
 - File octofussd.log octofussd.log added
 
L'import è sempre parziale, anche riducendo il numero degli utenti da importare.
Allego il cvs e output di octofussd.log.
root@serverfuss:~# dpkg -l octonet
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  octonet        0.2.5-1      all          OctoNet
root@serverfuss:~# dpkg -l octofussd
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  octofussd      8.0.19-1     all          server for remote computer lab ad
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from Michael Guggenberg to Mark Caglienzi
 
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from Mark Caglienzi to Michael Guggenberg
 
Michael cosa vedi nella finestra del browser? Si apre il dialog con la progress bar, poi quando si ferma? vedi errori o qualcosa del genere? Perche' guardando il log che hai allegato, si vede che non riceve piu' richieste, come se la finestra e/o il browser fossero stati chiusi, oppure si sia lasciata la pagina con il dialog della progress bar.
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    - File Screenshot - 05122017 - 10_27_49 AM.png Screenshot - 05122017 - 10_27_49 AM.png added
 - File import_1.csv import_1.csv added
 - File octofussd.log octofussd.log added
 
allego lo screenshot.
Riallego il file cvs.
Riallego octofussd.log
l'import sembra andare a buon fine, nessun errore (all users where imported!)
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    Ok, quindi possiamo chiudere? Cosa era successo nel tuo test precedente di diverso?
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - La progress bar mi sembra molto corta
 - Il file csv porta 200 utenti
 - Il log indica 120-121 utenti importati correttamente
 
- Il file csv e il log sono quelli relativi all'import che sembra andato a buon fine (cioè quello dell'ultimo screenshot) ?
 - Dopo aver cliccato sul bottone che porta alla lista utenti, ti ritrovi tutti gli utenti che erano presenti nel csv?
 
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    L'errore persiste.
octofussd.log riporta come ultimo utente create user121
2017-05-12T10:27:35+0200 [stdout#info] CREATE users/users/user121 {'uid': 'user121', 'primarygroup': 'studenti', 'homeDirectory': '/home/studenti/classe_B2011/user121
2017-05-12T10:27:35+0200 [twisted.python.log#info] 127.0.0.1 - - [12/May/2017:08:27:34 +0000] "POST /conf/ HTTP/1.1" 200 511 "-" "Python-xmlrpc/3.4"
import_1.cvs contiene 200 utenze
I file allegati corrispondono all' ultimo tentativo di importazione
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Status changed from Commenti to In elaborazione
 - Assignee changed from Michael Guggenberg to Mark Caglienzi
 
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Aggiungere un raise forzato nel codice backend quando arriva circa a metà import
 - Vedere cosa esce nei log e come si comporta la UI.
 
Ho aggiunto questo pezzo di codice:
if percentage >= 50:
    raise Exception("Ne hai già importati circa la metà")
	nel metodo che crea gli utenti leggendo il CSV.
- La UI non mostra nessun errore, anzi, la modal fa vedere il messaggio di tutto ok, MA la progress bar è piena solo a metà
 - Il log di octofussd non mostra nessun errore se non che smette di creare gli utenti quando arriva a metà
 - Il log di django è quello che segue:
 
[07/Jun/2017 13:59:27] "POST /users/csvimport_ajax HTTP/1.1" 200 138
Traceback (most recent call last):
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 179, in finish_response
    for data in self.result:
  File "/home/mark/truelite/FUSS/octonet/users/views.py", line 883, in users_generator
    raise Exception("Ne hai già importati circa la metà")
Exception: Ne hai già importati circa la metà
[07/Jun/2017 13:59:27] "POST /users/csvimport_ajax HTTP/1.1" 500 59
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 58100)
Traceback (most recent call last):
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 138, in run
    self.finish_response()
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 179, in finish_response
    for data in self.result:
  File "/home/mark/truelite/FUSS/octonet/users/views.py", line 883, in users_generator
    raise Exception("Ne hai già importati circa la metà")
Exception: Ne hai già importati circa la metà
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 141, in run
    self.handle_error()
  File "/home/mark/truelite/FUSS/octonet/django/core/servers/basehttp.py", line 95, in handle_error
    super(ServerHandler, self).handle_error()
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 368, in handle_error
    self.finish_response()
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 180, in finish_response
    self.write(data)
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 274, in write
    self.send_headers()
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 331, in send_headers
    if not self.origin_server or self.client_is_modern():
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 344, in client_is_modern
    return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
TypeError: 'NoneType' object is not subscriptable
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/lib/python3.5/socketserver.py", line 625, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python3.5/socketserver.py", line 354, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/home/mark/truelite/FUSS/octonet/django/core/servers/basehttp.py", line 102, in __init__
    super(WSGIRequestHandler, self).__init__(*args, **kwargs)
  File "/usr/lib/python3.5/socketserver.py", line 681, in __init__
    self.handle()
  File "/home/mark/truelite/FUSS/octonet/django/core/servers/basehttp.py", line 182, in handle
    handler.run(self.server.get_app())
  File "/usr/lib/python3.5/wsgiref/handlers.py", line 144, in run
    self.close()
  File "/usr/lib/python3.5/wsgiref/simple_server.py", line 36, in close
    self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
----------------------------------------
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    Quindi confermata la mia ipotesi. Wrappiamo il loop per intercettare l'eccezione, e restituiamo alla fine della esecuzione, prima di chiudere la connessione, l'elenco delle righe del file andate in errore, per poter informare l'utente.
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Assignee changed from Mark Caglienzi to Christopher R. Gabriel
 
Non so se così si possa fare, vista la StreamingHttpResponse.
Ho provato a wrappare la creazione e return della StreamingHttpResponse in un try, con la restituzione di una normale JsonResponse nell'except, contenente il messaggio dell'eccezione e gli utenti importati fin lì, ma non viene catchata/restituita, probabilmente perché la Streaming appena inizia a venir inviata poi impedisce di fare return di altro.
Continuo l'indagine e gli esperimenti
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from Christopher R. Gabriel to Mark Caglienzi
 
Ok, aggiornami dei risultati.
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Status changed from In elaborazione to Commenti
 - Assignee changed from Mark Caglienzi to Christopher R. Gabriel
 
- Incapsulata una specie di protocollo all'interno dello streaming
 - Gli errori di validazione sul form (ad es. username non scelto tra le colonne da importare) e sul CSV (ad es. utenti già esistenti) sono rimasti con la stessa gestione precedente
 - Il nuovo errore (cioè l'eccezione nel backend durante l'import quando tutto il resto è ok (colonne scelte correttamente e nessun utente duplicato)) viene gestito per forza diversamente
 users_generator()è tutto dentro untry: [...] except Exception as e:in modo che prenda su qualsiasi eccezione. In questo caso invia una stringa JSONabile contenentestatus="error", il testo dell'eccezione, la percentuale, e gli utenti correttamente importati fino a quel punto- Questa viene presa dal frontend, parsata in un JSON, e usata per compilare il template con un messaggio di errore che indica il problema nel backend, il testo dell'eccezione, e l'elenco degli utenti correttamente importati (così in questo modo l'utente può rimuoverli dal CSV e procedere con una nuova procedura di import, se è il caso.
 
- Mostrare l'elenco degli utenti non importati era più problematico
 - Questo mi è sembrato (anche con il supporto di Enrico) l'unico workaround per dare una UX un pochino usabile e chiara, visto il limite intrinseco di HTTP e StreamingHTTPResponse (Una volta che la streaming inizia, dà già 200 e non si può far restituire una response diversa a quel punto).
 
Dai miei esperimenti/test mi pare che sia possibile fare un po' tutto: import completamente corretti, import parziali per eccezione (c'è il raise commentato nel codice della view, se serve), prova di errori per utenti già presenti, o per errori di validazione form (cioè errori di scelta colonne da importare), anche uno di seguito all'altro (cioè provare import erronei dopo import corretti o viceversa, ecc...)
Codice pushato in t231 e non mergiato.
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from Christopher R. Gabriel to Michael Guggenberg
 
Pubblicato octonet 0.2.7 che include anche questo fix.
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    - File octofussd.log octofussd.log added
 
Portroppo anche dopo l'ultimo aggiornamento la situazione non è cambiata.
Provo ad importare i 200 utenti da file import_1.cvs, la statusbar non raggiunge 100%, octonet riporta di aver importato tutti gli utenti.
octofussd.log riporta 115 utenti creati e non da nessun errore.
Versioni installati:
octonet 0.2.10-1
octofuss 8.0.28-1
riallego il il file di importazione, octofussdlog
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    - Assignee changed from Michael Guggenberg to TRUELITE
 
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - Status changed from Commenti to In elaborazione
 - Assignee changed from TRUELITE to Mark Caglienzi
 
      
      Updated by Mark Caglienzi over 8 years ago
      
    
    - File test_import.csv test_import.csv added
 - Status changed from In elaborazione to Commenti
 - Assignee changed from Mark Caglienzi to Michael Guggenberg
 
Attualmente con le versioni octofussd 8.0.30-1 e octonet 0.2.10-1 non riusciamo a riprodurre il problema, abbiamo importato il file CSV allegato a questo messaggio (con quasi 1300 utenti) senza problemi.
      
      Updated by Paolo Dongilli over 8 years ago
      
    
    - File octofussd.log octofussd.log added
 - Assignee changed from Michael Guggenberg to Mark Caglienzi
 
Ho fatto un test con il CSV fornito da Mark. Allego il mio octofussd.log.
      
      Updated by Christopher R. Gabriel over 8 years ago
      
    
    - Assignee changed from Mark Caglienzi to Paolo Dongilli
 
Ho pubblicato nuova versione del pacchetto octonet, 0.2.13. Dopo aver riprodotto il problema, con questa soluzione non si ripresenta. Non e' un problema dell'applicazione, ma del demone che la fa girare (gunicorn).
Quando puoi, puoi verificare con questa nuova versione?
      
      Updated by Paolo Dongilli over 8 years ago
      
    
    - Assignee changed from Paolo Dongilli to Michael Guggenberg
 
Ho fatto l'aggiornamento di octonet sul nostro server ed ho testato con successo l'upload di tutte le 1292 utenze dal file https://work.fuss.bz.it/attachments/download/686/test_import.csv
Il ticket per me potrebbe essere chiuso. Lo passo comunque a Michael se vuole provare a fare un test anche lui prima della chiusura definitiva.
Grazie.
      
      Updated by Michael Guggenberg over 8 years ago
      
    
    - Assignee changed from Michael Guggenberg to TRUELITE
 - % Done changed from 0 to 100
 
Chiudo il ticket, la problematica durante l'import non si ripresenta più.
Grazie
Use the right keys when importing. refs: #231