<body>

Sitios web relacionados: PingBlog | Fotos

viernes, junio 30, 2006

Mañana juega Brasil: La última esperanza de Latinoamerica en el Mundial

Brasil, mundial Alemania 2006
Mañana me reuno en un bar con amigos y familia a ver el partido que me tiene los nervios de punta...


Mañana juega Brasil en contra de Francia. La última vez que jugaron frente a frente en 1988 yo estaba en Rio de Janeiro, festejando con unos amigos a lo grande. Y en eso Francia comenzó a ganar y a hacer goles, y Brasil simplemente no pudo....

La gran cagada.

Hoy Argentina fué eliminada del Mundial por Alemania, lo cual deja a Brasil (los campeones del mundo y proyección de lo que jamás podrá ser nuestra bañaperro Vinotinto) como la única representación de Suramerica, de los paises en desarrollo, en el Mundial.

Brasil siempre ha sido mi equipo favorito; Desde que comenzó el mundial me he puesto mi gorra en el trabajo ante la mirada incredula de los traders gringos que no entienden el fenomeno (pese a que su selección jugo mucho mejor que una Italia la cual ha sido una de las demostraciones de futbol más sucio de el mundial).

Pero el futbol no es justo, no ganan los mejores equipos y mañana se decidirá la suerte de Brasil. Yo como siempre los estaré apoyando :)

Lo siento por los amigos franceces que leen este blog, pero mañana se saldará una herida de 8 años, veanlo como un ajuste de cuentas pendientes :D

Así que Brasil, a GANAR :D

Actualización: Se repitió lo de hace 8 años atrás, reventaron a Brasil en la goma. Jugó sin energía y al final los intentos desesperados no lo ayudaron. Honestamente no me quedan equipos favoritos en el mundial, quizas gane Alemania aunque Portugal se merece llegar más lejos.

R.I.P. Brasil :(

Buscar en Technorati: , ,
Buscar en Blogalaxia: , ,

martes, junio 27, 2006

Vacaciones

Nashville 038
Me tomo un tiempo de merecidas vacaciones. Lejos del trading floor, las computadoras, comer frente al escritorio...


Y un montón de vainas más. Me voy a poder sumergir en la magia de el mundial sin que me importe un carajo el mundo o la politica, y es que vacaciones viene de el latin "vaca" (del verbo vacundus, que significa hacer un coño) y "ciones" (que es irse sin decirle a nadie). Y si no es así igual me importa un bledo ;)

No es mucho tiempo, pero igual se disfrutaran :D

Buscar en Technorati: ,
Buscar en Blogalaxia: ,

jueves, junio 22, 2006

Echando código: ¿Monitoreando servicios RPC usando Java, ONC RPC y el protocolo Jabber? (II)

java rpc
El taxista se encargó de decirle a su novia, y esta regó el cuento por allí...


En una primera parte les comentaba como hablar con NFS y a Rstatd desde Java usando RPC. Ahora vamos a terminar la aplicación enviando mensajes usando Jabber.

El protocolo de Jabber es muy completo. Sin embargo con esas características viene la complejidad, así que decidí tomar un atajo y en vez de complicarme la vida viendo como trabaja el protocolo me decidí a usar las libreria Smack (JiveSoftware, OpenSource). Como este articulo no se trata de como instalar un servidor de Jabber entonces vamos a utilizar una cuenta de Google Talk la cual habla el protocolo abierto XMPP .

No me gusta guardar ni usuarios ni passwords en el código, y mucho menos si el código va a estar en Internet :), así que modificamos un poco el archivo build.xml para leer un nuevo archivo de propiedades el cual tendrá los parametros requeridos para esta prueba.

Bueno, y el código super sencillo para probar la parte de la mensajería:

   1:package com.kodegeek.blog.monitoring.rpc;
2:
3:import org.jivesoftware.smack.Chat;
4:import org.jivesoftware.smack.XMPPConnection;
5:
6:import junit.framework.Assert;
7:import junit.framework.TestCase;
8:
9:
10:public class TestJabber extends TestCase {
11:
12:
13: protected void setUp() throws Exception {
14: super.setUp();
15: }
16:
17: /**
18: * Test the basic functionality of the Smack API
19: */
20: public void testJabber() {
21: XMPPConnection conn = null;
22: Chat chat = null;
23:
24: try {
25: Assert.assertNotNull("Please setup
the
address for the Google talk server",
System.getProperty("jabber.talk.server"));
26: Assert.assertNotNull("Please setup
the
receiving user for the Google talk server",
System.getProperty("jabber.talk.port"));
27: Assert.assertNotNull("Please setup
the
send address for the Google talk server",
System.getProperty("jabber.talk.send.user"));
28: Assert.assertNotNull("Please setup
the
send password for the Google talk server",
System.getProperty("jabber.talk.send.password"));
29: Assert.assertNotNull("Please setup
the
receiving user for the Google talk server",
System.getProperty("jabber.talk.rec.user"));
30:
31: conn =
32: new XMPPConnection(
33: System.getProperty("jabber.talk.server"),
34: Integer.parseInt(
System.getProperty("jabber.talk.port")));
35:
36: Assert.assertNotNull("XMPPConnection is null", conn);
37: Assert.assertTrue("We could not connect
to
the server", conn.isConnected());
38:
39: conn.login(
40: System.getProperty("jabber.talk.send.user"),
41: System.getProperty("jabber.talk.send.password"));
42: Assert.assertTrue("Could not authenticate",
conn.isAuthenticated());
43:
44: chat = conn.createChat(
System.getProperty("jabber.talk.rec.user"));
45: Assert.assertNotNull("Jabber Chat is null", chat);
46:
47: /**
48: * This is VERY important. If
you
don wait a little bit then the message will not
49: * be sent.
50: */
51: Thread.sleep(500);
52: chat.sendMessage("Hey, this is a message from http://KodeGeek.com");
53:
54: } catch (Throwable throwbl) {
55: Assert.fail("Got an exception: " + throwbl.toString());
56: throwbl.printStackTrace();
57: } finally {
58: if (conn != null) {
59: conn.close();
60: }
61: }
62: }
63:}

Aqui pueden ver como trabaja, una foto vale más que mil palabras:

jabbertest
Mandando mensajes a Jabber desde JUnit. En este caso una cuenta está en Jabber.org y la otra en talk.google.com


Si revizan el código fuente verán que tuve que poner un pequeño hack. Sin embargo no es un gran problema y la librería hace lo que promete.

Como siempre el código fuente y los binarios están disponibles para que jueguen con ellos. Espero esto les de algunas ideas de como monitorear sus servidores. En una última entrega les mostraré como poner todo junto.

Buscar en Technorati: , , , , ,
Buscar en Blogalaxia: , , , , ,

miércoles, junio 21, 2006

Echando código: ¿Monitoreando servicios RPC usando Java, ONC RPC y el protocolo Jabber? (I)

Java + ONRPC
La sabiduria de los taxistas

¿Que diria usted si yo le dijera que es posible hacer un sistema de monitoreo usando Java, ONCR RPC y el protocolo Jabber? Es mucho más sencillo de lo que usted cree y es algo que siempre quise hacer en la compañia en la cual trabajaba anteriormente (en la actual estoy trabajando similar, pero mucho más sofisticado :D) y nunca tuve tiempo de hacer.

Pero bueno, demasiada habladera de paja, veamos que hay que poner en orden:
  1. Asumimos que los servicios que queremos monitorear se basan en ONRC RPC. Ejemplo de ellos son NIS, NFS, Rusers, Rquota y en nuestro caso Rstatd que aunque es muchisimo más limitado que SNMP está presente en muchos servidores, corriendo de grátis :)
  2. ONRC RPC tiene unos archivos que describen como usar los servicios remoto, llamados 'stubs'. Si alguna vez ha utilizado RMI el concepto le será familiar. Pero hay un problema, los 'stubs' son muy similares a el lenguaje C, por lo que necesitamos una herramienta que nos sirva como puente. Para ello usamos el compilador de remote tea: jrpcgen.jar.
  3. Una vez obtenidos las interfaces y clientes en Java entonces las compilamos y nos valemos de las librerias de comunicación provistas por remote tea (onrpc.jar).
  4. De allí armamos los programas que van a hacer la consulta por medio de RPC. Luego nos preocupamos de como enviar los datos usando Jabber.
Lo primero que hay que hacer es generar las interfaces. El precompilador jrpcgen no tiene una tarea de Ant, sin embargo nosotros nos valemos de un macro con el cual preparamos las fuentes. Note que primero limpiamos los archivos '.x' utilizando al precompilador cpp y es allí cuando podemos usar a jrpcgen.

El macro en Ant es muy sencillo:
62:        <!-- Special macro to enable the RPC stub generation -->
63: <macrodef name="rpcgen">
64: <attribute name="xfile"/>
65: <attribute name="clientJavaFile"/>
66: <sequential>
67: <!-- Preprocess the 'x' files -->
68: <exec
69: executable="/usr/bin/cpp">
70: <arg line="${rpc.include.local}/@{xfile}.x"/>
71: <arg line="${rpc.include.local}/@{xfile}.cpp"/>
72: </exec>
73: <!-- Cleanup remaining artifacts -->
74: <replaceregexp
75: file="${rpc.include.local}/@{xfile}.cpp"
76: match="^#"
77: replace="//"
78: byline="true"/>
79: <!-- generate the Java classes -->
80: <java
81: classname="org.acplt.oncrpc.apps.jrpcgen.jrpcgen"
82: dir="${rpc.include.local}"
83: fork="true">
84: <classpath refid="path.classpath"/>
85: <arg value="-p"/>
86: <arg value="${package.tree}"/>
87: <arg value="-nobackup"/>
88: <arg value="-noserver"/>
89: <arg value="-verbose"/>
90: <arg value="-withcallinfo"/>
91: <arg value="-bean"/>
92: <arg value="-c"/>
93: <arg value="@{clientJavaFile}"/>
94: <arg value="-d"/>
95: <arg value="${stub}"/>
96: <arg value="@{xfile}.cpp"/>
97: </java>
98: </sequential>
99: </macrodef>
Una vez definido llamarlo es muy sencillo (note que primero generamos el código Java de las interfaces y luego más delante compilamos el código de la aplicación junto con el de las interfaces):
101:        <target 
102: name="rpcstub"
103: depends="init"
104: description="Create the RPC Java stub objects">
105: <copy
106: todir="${rpc.include.local}"
107: overwrite="true">
108: <fileset dir="${rpc.include.dir}">
109: <include name="*.x"/>
110: <include name="*.h"/>
111: </fileset>
112: </copy>
113: <rpcgen xfile="rstat" clientJavaFile="RstatClient"/>
114: <rpcgen xfile="mount" clientJavaFile="MountClient"/>
115: <rpcgen xfile="nfs_prot" clientJavaFile="NfsProtClient"/>
116: </target>
La compilación no depende de la generación de las interfaces ya que estas se guardan en CVS y si por algunas razón cambian es entonces que volveran a ser creadas. Es decir, una vez creadas las interfaces solamente nos tenemos que preocupar por compilar:
118:        <target 
119: name="build"
120: depends="init"
121: description="Compile the Java source code">
122: <!-- Compile the stub -->
123: <javac
124: srcdir="${stub}"
125: destdir="${build}"
126: deprecation="true"
127: optimize="false"
128: debug="true">
129: <include name="**/*.java"/>
130: <classpath refid="path.classpath"/>
131: </javac>
132: <!-- Compile the app -->
133: <javac
134: srcdir="${src}/main"
135: destdir="${build}"
136: deprecation="true"
137: optimize="false"
138: debug="true">
139: <include name="${package.path}/**/*.java"/>
140: <classpath refid="path.classpath"/>
141: </javac>
142: <copy
143: todir="${build}"
144: overwrite="true">
145: <fileset dir="${properties}/main">
146: <include name="${package.path}/**/*.properties"/>
147: </fileset>
148: </copy>
149: <copy
150: todir="${build}" overwrite="true">
151: <fileset dir=".">
152: <include name="log4j.properties"/>
153: </fileset>
154: </copy>
155: </target>
El siguiente paso es preparar las pruebas de unidad con Junit. Lo primero que hacemos es decirle a ant que es lo que queremos ejecutar y en que orden (si no está familiarizado con Junit, le recomiendo que busque una de las tantas referencias que hay en Internet):
205:        <target 
206: name="test"
207: depends="build"
208: description="Unit tests">
209: <echo>Running unit tests</echo>
210: <javac
211: srcdir="${src}/test"
212: destdir="${test}"
213: includes="${package.path}/**/Test*"
214: deprecation="true"
215: optimize="false"
216: debug="true">
217: <classpath refid="path.test"/>
218: </javac>
219:
220: <junit
221: fork="yes"
222: printsummary="on"
223: maxmemory="300m">
224: <classpath refid="path.test"/>
225: <formatter type="xml" />
226: <formatter type="plain" />
227: <!--
228: - As root, set the following property on the
/etc/exports
file:
229: /usr/local/src 127.0.0.1/255.0.0.0(insecure,ro)
230: - Then:
231: /etc/init.d/nfs start
232: -->
233: <sysproperty
234: key="test.nfs.dir"
235: value="/usr/local/src"/>
236:
237: <sysproperty
238: key="test.nfs.server"
239: value="localhost"/>
240:
241: <sysproperty
242: key="test.rstat.server"
243: value="localhost"/>
244:
245: <!-- Wait 35 seconds -->
246: <sysproperty
247: key="test.rstat.wait"
248: value="35000"/>
249:
250: <test
251: name="${testcase}"
252: todir="${test}"
253: if="testcase"/>
254:
255: <batchtest
256: todir="${test}"
257: unless="testcase">
258: <fileset
259: dir="${test}"
260: includes="**/Test*.class"/>
261: </batchtest>
262: </junit>
263:
264: <junitreport todir="${test}">
265: <fileset dir="${test}">
266: <include name="TEST-*.xml"/>
267: </fileset>
268: <report format="frames" todir="${test}"/>
269: </junitreport>
270: </target>
Es entonces cuando podremos utilizar las clases cliente. Me gusta probar las cosas antes de ponerlas juntas, así que escribí algunas pruebas de unidad (Unit tests) con JUnit vemos que tan bien o mal están las clases generadas:

   1:package com.kodegeek.blog.monitoring.rpc;
2:
3:import java.net.InetAddress;
4:import java.util.ResourceBundle;
5:
6:import junit.framework.Assert;
7:import junit.framework.TestCase;
8:
9:import org.acplt.oncrpc.OncRpcClientAuthUnix;
10:import org.acplt.oncrpc.OncRpcProtocols;
11:
12:public class TestRpcStubs extends TestCase {
13:
14: /**
15: * Default max timeout value, in miliseconds
16: */
17: public static final int MAX_TIMEOUT = 1000*60;
18:
19: private static ResourceBundle NFS_BUNDLE;
20: private static ResourceBundle RSTAT_BUNDLE;
21:
22: {
23: NFS_BUNDLE = ResourceBundle.getBundle(
NfsPing.class.getName());
24: RSTAT_BUNDLE = ResourceBundle.getBundle(
RstatPing.class.getName());
25: }
26:
27: protected void setUp() throws Exception {
28: super.setUp();
29: System.out.println("Make sure all the services are running
with '/usr/sbin/rpcinfo -p'");
30: }
31:
32: /**
33: * Simple test for the NFS client, using the generated RPC stubs directly
34: *
35: */
36: public void testNfs() {
37: MountClient mount = null;
38: exports exportsList = null;
39: fhstatus fhStatus = null;
40: OncRpcClientAuthUnix authUnix = null;
41: try {
42: authUnix = new OncRpcClientAuthUnix(
43: System.getProperty("test.nfs.server"),
44: Integer.parseInt(
NFS_BUNDLE.getString("NfsPing.user.id")),
45: Integer.parseInt(
NFS_BUNDLE.getString("NfsPing.user.group"))
46: );
47: Assert.assertNotNull("Auth Unix is null", authUnix);
48: // Get the list of exported directories
49: mount = new MountClient(
50: InetAddress.getByName(
System.getProperty("test.nfs.server")),
51: OncRpcProtocols.ONCRPC_TCP);
52: Assert.assertNotNull("Mount is null", mount);
53: exportsList = mount.MOUNTPROC_EXPORT_1();
54: Assert.assertNotNull("Export list is null", exportsList);
55: exportnode node = exportsList.value;
56: Assert.assertNotNull("No nodes are being exported", node);
57: while (node != null) {
58: Object [] nodeForm = new Object[1];
59: nodeForm[0] = node.ex_dir.value;
60: System.out.printf(
61: NFS_BUNDLE.getString(
"
NfsPing.msg.exportedFs"), nodeForm
62: );
63:
64: mount.getClient().setAuth(authUnix);
65: mount.getClient().setTimeout(MAX_TIMEOUT);
66:
67: fhStatus = mount.MOUNTPROC_MNT_1(new dirpath(
System.getProperty("test.nfs.dir")));
68: if (fhStatus == null) {
69: Assert.fail("unable to get fhStatus for: " +
System.getProperty("test.nfs.dir"));
70: }
71: // Get the next node
72: node = node.ex_next.value;
73: }
74: } catch (Throwable throwbl) {
75: Assert.fail("Got an exception: " + throwbl.toString());
76: throwbl.printStackTrace();
77: } finally {
78: // Empty for now
79: }
80: }
81:
82: /**
83: * Simple test for Rstat, using the generated RPC stubs directly
84: * Timestamps are separated into seconds (standard UNIX time) and
85: * microseconds. The availability of a current timestamp allows proper
86: * calculation of the interval between measurements without worrying
87: * about network latency.
88: *
89: * Most values are counters. To get the real numbers you have to
90: * fetch() samples regularly and divide the counter increments
91: * by the time interval between the samples.
92: *
93: * The cpu_time array holds the ticks spent in the various CPU states
94: * (averaged over all CPUs). If you know the regular tick rate of the target
95: * system you may calculate the number of CPUs from the sum of C<cpu_time>
96: * increments and the time interval between the samples. Most often you
97: * will be interested in the percentage of CPU states only.
98: */
99: public void testRstat() {
100: OncRpcClientAuthUnix authUnix = null;
101: RstatClient rstat = null;
102: statstime stats = null;
103: statstime stats2 = null;
104: try {
105: authUnix = new OncRpcClientAuthUnix(
106: System.getProperty("test.rstat.server"),
107: Integer.parseInt(RSTAT_BUNDLE.getString(
"
RstatPing.user.id")),
108: Integer.parseInt(RSTAT_BUNDLE.getString(
"RstatPing.user.group"))
109: );
110: Assert.assertNotNull("Auth Unix is null", authUnix);
111:
112: rstat = new RstatClient(
113: InetAddress.getByName(System.getProperty(
"
test.rstat.server")),
114: OncRpcProtocols.ONCRPC_UDP
115: );
116: Assert.assertNotNull("Rstat is null", rstat);
117: rstat.getClient().setAuth(authUnix);
118: rstat.getClient().setTimeout(MAX_TIMEOUT);
119: stats = rstat.RSTATPROC_STATS_3();
120: Assert.assertNotNull("statsswtch stats is null", stats);
121:
122: // Now wait a little bit before taking the next snapshot
123: long wait = Long.parseLong(System.getProperty("test.rstat.wait"));
124: Thread.sleep(wait);
125:
126: // Get another snapshot
127: stats2 = rstat.RSTATPROC_STATS_3();
128:
129: long timeElaps = stats2.getCurtime().tv_sec -
stats.getCurtime().tv_sec;
130:
131: Object [] statColl = new Object[23];
132: statColl[0] = new Long((stats2.if_collisions -
stats.if_collisions)/ timeElaps);
133: statColl[1] = new Long((stats2.if_ierrors -
stats.if_ierrors) /timeElaps);
134: statColl[2] = new Long((stats2.if_ipackets -
stats.if_ipackets) /
timeElaps);
135: statColl[3] = new Long((stats2.if_oerrors -
stats.if_oerrors) /timeElaps);
136: statColl[4] = new Long((stats2.if_opackets -
stats.if_opackets) /timeElaps);
137: statColl[5] = new Long((stats2.v_intr -
stats.v_intr) /timeElaps);
138: statColl[6] = new Long((stats2.v_pgpgin -
stats.v_pgpgin) /timeElaps);
139: statColl[7] = new Long((stats2.v_pgpgout -
stats.v_pgpgout) /timeElaps);
140: statColl[8] = new Long((stats2.v_pswpin -
stats.v_pswpin) /timeElaps);
141: statColl[9] = new Long((stats2.v_pswpout -
stats.v_pswpout) /timeElaps);
142: statColl[10] = new Long((stats2.v_swtch -
stats.v_swtch) /timeElaps);
143: statColl[11] = new Double(stats2.getAvenrun(0) / 256.0);
144: statColl[12] = new Double(stats2.getAvenrun(1) / 256.0);
145: statColl[13] = new Double(stats2.getAvenrun(2) / 256.0)