MarioDebian, mi devlog

Bitácora de un desarrollador newbie.

El look and feel es importante TcosMonitor 0.0.10

Para que una aplicación gráfica guste, lo primero es que funcione bien, pero lo segundo y en este órden es que sea agradable a la vista y no parezca que se arrastra...

Por eso he estado implementando que algunas acciones de TcosMonitor se ejecuten en hilos (Threads) para que la interfaz no se congele, todavía no funciona todo lo bien que quisiera pero la fluided se nota bastante.

Por ejemplo, el descubrimiento de equipos, es decir, las máquinas conectadas al puerto 6000 del servidor (realmente a 6000-6009 porque parece que LTSP si se configura startx en un screen distinto del 0 se conecta a otro puerto... )
Esto es el código que se ejecuta al pulsar el botón de actualizar:

def on_refreshbutton_click(self,widget): if self.init.searching: print_debug( "on_refreshbutton_click() searching TRUE" ) # FIXME show a msg return self.write_into_statusbar ( _("Searching for connected hosts...") ) allclients=self.localdata.GetAllClients() if len(allclients) == 0: self.write_into_statusbar ( _("Not connected hosts found.") )

return
else:
txt=_("Found %d hosts, retrieving data..." ) %len(allclients)
self.write_into_statusbar ( txt )
# populate_list in a thread
Thread( target=self.init.populate_hostlist, args=([allclients]) ).start() return

La acción que más tiempo lleva es tomar usuario, nombre de host, número de procesos, tiempo conectado, y estado del bloqueo de pantalla para cada equipo, por lo que esto se ejecuta en un nuevo Thread (línea negrita), siendo el trozo subrallado la función que hace todas estas cosas.


La función populate_hostlist de la clase Initialize es la siguiente:

def populate_hostlist(self, clients): print_debug ( "populate_hostlist() init" ) start1=time() if self.searching:
return
self.searching=True # clean list print_debug ( "populate_hostlist() clear list!!!" ) self.model.clear() COL_HOST, COL_IP, COL_USERNAME, COL_ACTIVE, COL_LOGGED, COL_BLOCKED, COL_PROCESS, COL_TIME = range(8) inactive_image = gtk.gdk.pixbuf_new_from_file(shared.GLADE_DIR + '/images/inactive.png') active_image = gtk.gdk.pixbuf_new_from_file(shared.GLADE_DIR + '/images/active.png') logged_image = gtk.gdk.pixbuf_new_from_file(shared.GLADE_DIR + '/images/logged.png') unlogged_image = gtk.gdk.pixbuf_new_from_file(shared.GLADE_DIR + '/images/unlogged.png') locked_image = gtk.gdk.pixbuf_new_from_file(shared.GLADE_DIR + '/images/locked.png') unlocked_image = gtk.gdk.pixbuf_new_from_file(shared.GLADE_DIR + '/images/unlocked.png') i=0 for host in clients: i += 1 self.main.localdata.newhost(host) self.main.xmlrpc.newhost (host) ip=host hostname=self.main.localdata.GetHostname(ip) username=self.main.localdata.GetUsername(ip) num_process=self.main.localdata.GetNumProcess(ip) time_logged=self.main.localdata.GetTimeLogged(ip) if self.main.localdata.IsActive(ip): image_active=active_image else: image_active=inactive_image if self.main.localdata.IsLogged(ip): image_logged=logged_image else: image_logged=unlogged_image if self.main.localdata.IsBlocked(host): image_blocked=locked_image else: image_blocked=unlocked_image gtk.threads_enter() self.iter = self.model.append (None) self.model.set_value (self.iter, COL_HOST, hostname ) self.model.set_value (self.iter, COL_IP, host ) self.model.set_value (self.iter, COL_USERNAME, username ) self.model.set_value (self.iter, COL_ACTIVE, image_active ) self.model.set_value (self.iter, COL_LOGGED, image_logged) self.model.set_value (self.iter, COL_BLOCKED, image_blocked) self.model.set_value (self.iter, COL_PROCESS, num_process ) self.model.set_value (self.iter, COL_TIME, time_logged) gtk.threads_leave() crono(start1, "populate_host_list(%s)" %(ip) ) print_debug ( "populate_hostlist() END" ) self.searching=False return

El código en negrita es lo más crítico de la función ya que accede al interfaz gráfico GTK para completar los valores del TreeView, por eso van encerrados entre llamadas a gtk.threads_{enter,leave}. La función crono no es más que un cronómetro que resta dos variables de tiempo para saber cuando se tarda en ejecutar el proceso, si se desactiva el modo debug hay muchas cosas que ya no se ejecutan como ésta.

Como se puede adivinar self.searching es un bloqueo para que no se llame a esta función si ya se está ejecutando.

Funciona bastante bien pero de vez en cuando y aleatoriamente da una extraña violación de segmento acompañada de un fallo de tubería de wc, que me da que pensar que algo falla en la extracción del número de procesos:

cmd=" ps aux|grep "^%s "| wc -l" %(self.username)

He añadido un par de condiciones a la función que lo hace y parece que ya no ha vuelto a suceder.

También estoy implementando un control de cache de los datos, por ejemplo, guardar en un array si el equipo está vivo (responde a los ping), los puertos abiertos, usuario y nombre de equipo, para que sólo se calculen la primera vez y el resto se devuelvan desde cache, para evitar problemas cada elemento del array (cada host) tiene un tiempo de vida que si se supera se vuelve a pedir, (configurable desde las preferencias).

Para terminar unas capturas de la interfaz un poco más bonita con sus iconos de menús, con una red simple de 3 equipos funcionando sobre 3 vmplayer en mi pobre portátil:
  • tcos1 es un equipo basado en TCOS
  • tcos2 es un equipo basado en LTSP 4.2
  • tcos3 es un equipo basado en PXES 1.2
Con esto se demuestra que TcosMonitor ya funciona medianamente en las tres plataformas.






ATENCIÓN:

Los paquetes los he partido para no tener que instalar cosas que no vamos a usar:

tcosmonitor - interfaz pyhton
tcos-tcosmonitor - complementos para que tcosmonitor funcione con tcos
pxes-1.0-tcosmonitor - complementos para que tcosmonitor funcione con pxes-1.0
pxes-1.1-tcosmonitor - complementos para que tcosmonitor funcione con pxes-1.1
pxes-1.2-tcosmonitor - complementos para que tcosmonitor funcione con pxes1.2
ltsp-tcosmonitor - complementos para que tcosmonitor funcione con LTSP (instalado en /opt/ltsp)

El mirror donde siempre:

deb http://soleup.eup.uva.es/tcos/debian unstable main


Articulos relacionados:

Comentarios

  1. Adivina adivinanza Joeeeeeer la leche
    12/07/2006 | 23:53

    Hace mucho que no paso por aquí y ando un poco perdido (lo exámenes) pero prometo ponerme al día y empezar a criticar (que se me da de puta madre) sobre todo en el tema de que parezca agradable a la vista, por que no podemos esperar mucho de un tío que dice que Gnome está hecho con más gusto que KDE.

    Un besito golfo

    PD: El sistema de envio no funciona con OPERA. ¿Quién usa Opera? pues en las prácticas que curro usan Opera, acojonante.

Comentarios cerrados