cdef extern from "moira/moira.h": int mr_krb5_auth(char * prog) int mr_auth(char * prog) int mr_connect(char * server) int mr_disconnect() int mr_host(char * host_buf, int buf_size) int mr_motd(char ** motd) int mr_noop() int mr_query(char * handle, int argc, char ** argv, int (*callback)(int, char **, void *), object callarg) int mr_access(char *handle, int argc, char ** argv) int mr_proxy(char *principal, char *orig_authtype) int mr_version(int version) enum: MR_SUCCESS MR_CONT MR_VERSION_LOW cdef extern from "com_err.h": ctypedef long errcode_t char * error_message(errcode_t) cdef extern from "stdlib.h": ctypedef unsigned long size_t void * malloc(size_t size) void free(void * ptr) class MoiraException(Exception): def code(self): return self.args[0] code = property(code) __connected = False def _error(code): raise MoiraException, (code, error_message(code)) def connect(server=''): """ Establish a connection to a Moira server. A server may be specified, but it is optional. If specified, it should be of the form hostname:portname. Portname will be looked up in /etc/services if specified, but it is optional as well. If no server is specified, the server will be found from the MOIRASERVER environment variable, Hesiod, or a compiled in default (in that order). This function raises a MoiraException if the connection is not successful. """ global __connected if __connected: disconnect() status = mr_connect(server) if status != MR_SUCCESS: _error(status) else: __connected = True def disconnect(): """ Disconnect from the active Moira server """ global __connected if __connected: mr_disconnect() __connected = False def auth(program, krb4=False): """ Authenticate to the Moira server with Kerberos tickets. If krb4 is True, then Kerberos version 4 will be used. Otherwise, Kerberos version 5 is used. The program argument identifies the connecting program to the Moira server. This is used for setting the modwith field when modifications are made. Note that the use of Kerberos version 4 is deprecated and highly discouraged """ if krb4: status = mr_auth(program) else: status = mr_krb5_auth(program) if status != MR_SUCCESS: _error(status) def host(): """ Return the name of the host the client is connected to. """ cdef char buffer[512] status = mr_host(buffer, 512) if status != MR_SUCCESS: _error(status) return buffer def motd(): """ Retrieve the current message of the day from the server. """ cdef char * motd status = mr_motd(&motd) if status != MR_SUCCESS: _error(status) if motd != NULL: return motd def noop(): """ Does "no operation" to the server, just making sure it's still there """ status = mr_noop() if status: _error(status) def _access(handle, *args): """ Verifies that the authenticated user has the access to perform the given query. """ cdef int argc, i argc = len(args) cdef char ** argv argv = malloc(argc * sizeof(char *)) if argv != NULL: for i in xrange(argc): argv[i] = args[i] status = mr_access(handle, argc, argv) free(argv) if status: _error(status) def _query(handle, callback, *args): cdef int argc, i argc = len(args) cdef char ** argv argv = malloc(argc * sizeof(char *)) if argv != NULL: for i in xrange(argc): argv[i] = args[i] status = mr_query(handle, argc, argv, _call_python_callback, callback) free(argv) if status: _error(status) def proxy(principal, orig_authtype): """ Authenticate as a proxy for another principal. For those with sufficient privilege, proxy allows an authenticated user to impersonate another. The principal argument contains the Kerberos principal for which this user is proxying, and orig_authtype is the mechanism by which the proxied user originally authenticated to the proxier. """ status = mr_proxy(principal, orig_authtype) if status != MR_SUCCESS: _error(status) def version(ver): """ Exchange query version info with the server. In order to allow changing queries without breaking client compatibility, the Moira server supports multiple versions of the query list simultaneously. Use version to change which one is currently being used. The ver argument is a signed integer containing the query version to use. If ver is -1, Moira will always use the more recent query version. version returns True if you requested the most recent version number and False if you requested an out-of-date version number. """ status = mr_version(ver) if status == MR_SUCCESS: return True elif status == MR_VERSION_LOW: return False else: _error(status) cdef int _call_python_callback(int argc, char ** argv, void * hint): cdef object callback callback = hint result = [] cdef int i for i in xrange(argc): result.append(argv[i]) callback(tuple(result)) return MR_CONT