Echando código: ¿Como monitorear a NFS usando Java? (hablemos ONC RPC, II)

Manhattan
Bueno, vamos a ver ahora como terminar montar el puente MOUNT / NFS con RPC para monitorear un servidor (las piezas encajan perfectamente)

Esta es la continuación de el articulo anterior. Sólo que esta vez nuestro cliente va a hacer algo más interesante que sólo conectarse al servidor, vamos a obtener el listado de los archivos que están siendo exportados por el servidor de NFS.

Sólo les voy a mostrar el código de la aplicación, no tiene caso ver el código de los archivos generados con JRPCGEN:

   1:package com.blogspot.elangelnegro.nfs.app;
2:
3:import java.net.InetAddress;
4:
5:import java.io.IOException;
6:
7:import org.acplt.oncrpc.OncRpcProgramNotRegisteredException;
8:import org.acplt.oncrpc.OncRpcClientAuthUnix;
9:import org.acplt.oncrpc.OncRpcAuthenticationException;
10:import org.acplt.oncrpc.OncRpcException;
11:import org.acplt.oncrpc.OncRpcProtocols;
12:import org.acplt.oncrpc.OncRpcAuthStatus;
13:
14:import com.blogspot.elangelnegro.nfs.client.nfs_protClient;
15:import com.blogspot.elangelnegro.nfs.client.mountClient;
16:import com.blogspot.elangelnegro.nfs.client.readdirargs;
17:import com.blogspot.elangelnegro.nfs.client.readdirres;
18:import com.blogspot.elangelnegro.nfs.client.exports;
19:import com.blogspot.elangelnegro.nfs.client.exportnode;
20:import com.blogspot.elangelnegro.nfs.client.dirpath;
21:import com.blogspot.elangelnegro.nfs.client.fhstatus;
22:
23:import com.blogspot.elangelnegro.nfs.client.nfscookie;
24:import com.blogspot.elangelnegro.nfs.client.nfs_prot;
25:import com.blogspot.elangelnegro.nfs.client.nfsstat;
26:import com.blogspot.elangelnegro.nfs.client.nfs_fh;
27:import com.blogspot.elangelnegro.nfs.client.entry;
28:
29:/**
30: * This class does a read only 'Ping' against a NFS server, by getting the list
31: * of files on a given directory.
32: *
33: * Blog: El Angel Negro - http://elangelnegro.blogspot.com/
34: *
35: * License: GPL
36: *
37: * Please consult the following RFC as they contain usefull information about the protocol:
38: * <ul>
39: * <li> XDR: External Data Representation standard, http://www.faqs.org/rfcs/rfc1014.html
40: * <li> RPC: Remote Procedure Call Protocol Specification Version 2, http://www.ietf.org/rfc/rfc1831.txt
41: * <li> NFS: Network File System Protocol specification, http://www.faqs.org/rfcs/rfc1094.html
42: * </ul>
43: *
44: * @author Jose Vicente Nunez Zuleta (josevnz@users.sourceforge.net)
45: * @version 0.1 - 07/17/2005
46: */
47:public final class Ping {
48:
49: /**
50: * Error exit code
51: */
52: public static final int ERROR_EXIT_CODE=192;
53:
54: /**
55: * User and group to be used when authenticating
56: * You can get that information yourself from the /etc/passwd file:
57: * perl -F':' -lane 'print "$F[2] $F[3]" if $F[0] eq "josevnz"' /etc/passwd
58: */
59: public static final int [] USER_AND_GROUP = {500, 500};
60:
61: /**
62: * Constant for the number of dirs 'up to count bytes'
63: */
64: public static final int MAX_DIRS = 10000;
65:
66: /**
67: * Command line argument processing
68: * @param args args[0] is the hostname to check.
69: * @throws Exception If any error.
70: * @since 0.1
71: */
72: public static void main(String [] args) throws Exception {
73: nfs_protClient nfs = null;
74: mountClient mount = null;
75: readdirres dirResult = null;
76: readdirargs dirArgs = null;
77: exports exportsList = null;
78: fhstatus fhStatus = null;
79: boolean hasDir = false;
80: OncRpcClientAuthUnix authUnix = null;
81: if ( ! ( (args != null) && (args.length == 2) && (args[0] != null) && (args[1] != null)) ) {
82: throw new IllegalArgumentException("Please specify the NFS server host / directory to check!");
83: }
84: try {
85: authUnix = new OncRpcClientAuthUnix(args[1], USER_AND_GROUP[0], USER_AND_GROUP[1]);
86: // Get some information with mount
87: mount = new mountClient(InetAddress.getByName(args[0]), OncRpcProtocols.ONCRPC_TCP);
88: System.out.println("Connected with Mountd");
89: // Get the list of exported directories
90: exportsList = mount.MOUNTPROC_EXPORT_1();
91: exportnode node = exportsList.value;
92: while (node != null) {
93: System.out.println(
94: "Exported filesystem: " +
95: node.ex_dir.value
96: );
97: if (node.ex_dir.value.equals(args[1])) {
98: hasDir = true;
99: }
100: node = node.ex_next.value;
101: }
102:
103: // Do the remote NFS server has the directory we are looking for?
104: if (hasDir) {
105:
106: mount.getClient().setAuth(authUnix);
107: fhStatus = mount.MOUNTPROC_MNT_1(new dirpath(args[1]));
108: if (fhStatus.fhs_status != 0) {
109: throw new IOException("There was a problem mounting the directory: '" + args[1] + "', reason: " + getNFSCodeReason(fhStatus.fhs_status));
110: }
111: nfs = new nfs_protClient(InetAddress.getByName(args[0]), OncRpcProtocols.ONCRPC_TCP);
112: nfs.getClient().setAuth(authUnix);
113: System.out.println("Connected with NFSD");
114:
115: /*
116: * Try to get the directory listing. Up to here all has been generic.
117: * The RFC 1094 describes which methods can be called for a NFS server.
118: *
119: */
120: dirArgs = new readdirargs();
121: dirArgs.count = MAX_DIRS;
122: // Create an empty 'zero' NFS cookie, first time read
123: byte [] zeroCookie = new byte[nfs_prot.NFS_COOKIESIZE];
124: for (int i = 0; i < nfs_prot.NFS_COOKIESIZE; i++) {
125: zeroCookie[i] = 0;
126: }
127: nfscookie cookie = new nfscookie(zeroCookie);
128: dirArgs.cookie = cookie;
129:
130: // Use the information obtained for the previous NFS file handle
131: nfs_fh nfsFh = new nfs_fh();
132: nfsFh.data = fhStatus.fhs_fhandle.value;
133: dirArgs.dir = nfsFh;
134: dirResult = nfs.NFSPROC_READDIR_2(dirArgs);
135: if (dirResult.status != 0) {
136: throw new IOException("Got an error from the NFS server: " + getNFSCodeReason(dirResult.status));
137: }
138: entry currEntry = dirResult.reply.entries;
139: System.out.println("Current directory entries: ");
140: while(currEntry != null) {
141: System.out.println(currEntry.name.value);
142: currEntry = currEntry.nextentry;
143: }
144: }
145: } catch (OncRpcAuthenticationException exp) {
146: // Get a better explanation why the auth failed
147: switch (exp.getReason()) {
148: case OncRpcAuthStatus.ONCRPC_AUTH_BADCRED:
149: System.err.println("Bad credential (seal broken)");
150: break;
151: case OncRpcAuthStatus.ONCRPC_AUTH_BADVERF:
152: System.err.println("Bad verifier (seal broken)");
153: break;
154: case OncRpcAuthStatus.ONCRPC_AUTH_FAILED:
155: System.err.println("Reason unknown");
156: break;
157: case OncRpcAuthStatus.ONCRPC_AUTH_INVALIDRESP:
158: System.err.println("Bogus response verifier");
159: break;
160: case OncRpcAuthStatus.ONCRPC_AUTH_REJECTEDCRED:
161: System.err.println("Client must begin new session");
162: break;
163: case OncRpcAuthStatus.ONCRPC_AUTH_REJECTEDVERF:
164: System.err.println("Verifier expired or replayed");
165: break;
166: case OncRpcAuthStatus.ONCRPC_AUTH_TOOWEAK:
167: System.err.println("Rejected for security reasons");
168: break;
169: }
170: throw exp;
171: } catch (OncRpcProgramNotRegisteredException exp) {
172: System.err.println("ONC/RPC program server not found");
173: throw exp;
174: } catch (OncRpcException exp) {
175: System.err.println("Could not contact portmapper:");
176: exp.printStackTrace(System.err);
177: throw exp;
178: } catch (IOException exp) {
179: System.err.println("Could not contact portmapper:");
180: exp.printStackTrace(System.err);
181: throw exp;
182: } finally {
183: if (mount != null) {
184: try {
185: if (hasDir) {
186: try {
187: mount.MOUNTPROC_UMNTALL_1();
188: } catch (Exception ignoreInner) {
189: // Ignore any exceptions here
190: }
191: }
192: mount.close();
193: } catch (Exception ignore) {
194: // Do nothing
195: }
196: }
197: if (nfs != null) {
198: try {
199: nfs.close();
200: } catch (Exception ignore) {
201: // Do nothing
202: }
203: }
204: }
205: }
206:
207: /**
208: * Map the NFS return code to messages in English
209: * @param theCode
210: * @return String Translated String
211: */
212: private static String getNFSCodeReason(int theCode) {
213: String reason = null;
214: switch (theCode) {
215: case nfsstat.NFS_OK:
216: reason = "NFS OK"; break;
217: case nfsstat.NFSERR_PERM:
218: reason = "NFSERR PERM"; break;
219: case nfsstat.NFSERR_NOENT:
220: reason = "NFSERR NOENT"; break;
221: case nfsstat.NFSERR_IO:
222: reason = "NFSERR IO"; break;
223: case nfsstat.NFSERR_NXIO:
224: reason = "NFSERR NXIO"; break;
225: case nfsstat.NFSERR_ACCES:
226: reason = "NFSERR ACCES"; break;
227: case nfsstat.NFSERR_EXIST:
228: reason = "NFSERR EXIST"; break;
229: case nfsstat.NFSERR_NODEV:
230: reason = "NFSERR NODEV"; break;
231: case nfsstat.NFSERR_NOTDIR:
232: reason = "NFSERR NOTDIR"; break;
233: case nfsstat.NFSERR_ISDIR:
234: reason = "NFSERR ISDIR"; break;
235: case nfsstat.NFSERR_FBIG:
236: reason = "NFSERR FBIG"; break;
237: case nfsstat.NFSERR_NOSPC:
238: reason = "NFSERR NOSPC"; break;
239: case nfsstat.NFSERR_ROFS:
240: reason = "NFSERR ROFS"; break;
241: case nfsstat.NFSERR_NAMETOOLONG:
242: reason = "NFSERR NAMETOOLONG"; break;
243: case nfsstat.NFSERR_NOTEMPTY:
244: reason = "NFSERR NOTEMPTY"; break;
245: case nfsstat.NFSERR_DQUOT:
246: reason = "NFSERR DQUOT"; break;
247: case nfsstat.NFSERR_STALE:
248: reason = "NFSERR STALE"; break;
249: case nfsstat.NFSERR_WFLUSH:
250: reason = "NFSERR WFLUSH"; break;
251: default:
252: reason = "UNKNOWN CODE"; break;
253: }
254: return reason;
255: }
256:}

La salida de nuestro programa es la siguiente:

Connected with Mountd
Exported filesystem: /usr/local/src
Connected with NFSD
Current directory entries:
linux-wlan-ng-0.2.1-pre26
..
WAG54GV2
.

Debo admitir que lo único que no me gustó de las librerías es la cantidad tan grande de objetos intermedios que hay que crear; Por otro lado no me tomó mucho darme una idea de que metodos llamar y como hacerlo, gracias a lo intuitivo de las clases y el contenido de los RFC.

Ahora piense en las posibilidades de monitoreo utilizando Java y RPC:

  • NIS
  • Espacio en disco, interfaces de redes, carga de el CPU
  • NFS (Ya vimos algo de eso)
  • Y cualquier otro servicio en su máquina que hable RPC

Los dejo con un enlace al código fuente, binarios y las librerías de Remote Tea. Bajeselo, compilelo y juegue con él. Y sobre todo, opine, quizas todos podamos sacar algo interesante de todo esto.

Etiquetas en Technorrati: