Moab Workload Manager

Wiki Socket Protocol Description

The Moab scheduler uses a simple protocol for socket connections to the user client and the resource manager as described below:

<SIZE><CHAR>CK=<CKSUM><WS>TS=<TIMESTAMP><WS>AUTH=<AUTH><WS>DT=<DATA>

An example header follows:

00001057 CK=cdf6d7a7ad45026f TS=922401962 AUTH=sched DT=<DATA>

where '<DATA>' is replaced by actual message data.

Checksum Algorithm ('C' version)

#define MAX_CKSUM_ITERATION 4 int GetChecksum( char *Buf, int BufSize, char *Checksum, char *CSKey) /* Note: pass in secret key */ { unsigned int crc; unsigned int lword; unsigned int irword; int index; unsigned int Seed; Seed = (unsigned int)strtoul(CSKey,NULL,0); crc = 0; for (index = 0;index < BufSize;index++) { crc = (unsigned int)DoCRC((unsigned short)crc,Buf[index]); } lword = crc; irword = Seed; PSDES(&lword,&irword); sprintf(Checksum,"%08x%08x", lword, irword); return(SUCCESS); } unsigned short DoCRC( unsigned short crc, unsigned char onech) { int index; unsigned int ans; ans = (crc ^ onech << 8); for (index = 0;index < 8;index++) { if (ans & 0x8000) ans = (ans <<= 1) ^ 4129; else ans <<= 1; } return((unsigned short)ans); } int PSDES( unsigned int *lword, unsigned int *irword) { int index; unsigned int ia; unsigned int ib; unsigned int iswap; unsigned int itmph; unsigned int itmpl; static unsigned int c1[MAX_CKSUM_ITERATION] = { 0xcba4e531, 0x537158eb, 0x145cdc3c, 0x0d3fdeb2 }; static unsigned int c2[MAX_CKSUM_ITERATION] = { 0x12be4590, 0xab54ce58, 0x6954c7a6, 0x15a2ca46 }; itmph = 0; itmpl = 0; for (index = 0;index < MAX_CKSUM_ITERATION;index++) { iswap = *irword; ia = iswap ^ c1[index]; itmpl = ia & 0xffff; itmph = ia >> 16; ib = (itmpl * itmpl) + ~(itmph*itmph); ia = (ib >> 16) | ((ib & 0xffff) << 16); *irword = (*lword) ^ ((ia ^ c2[index]) + (itmpl * itmph)); *lword = iswap; } return(SUCCESS); }

Header Creation (PERL code)

(taken from PNNL's QBank client code)

################################################################################ # # subroutine wiki($COMMAND) # # Sends command to Moab server and returns the parsed result and status # ################################################################################ sub wiki { my($COMMAND,$REQUEST,$result); my($sockaddr,$hostname); my($name,$aliases,$proto,$port,$type,$len,$thisaddr); my($thisport,$thatport,$response,$result); $COMMAND = shift; # # Establish socket connection # $sockaddr = 'S n a4 x8'; chop ($hostname = `hostname`); ($name,$aliases,$proto)=getprotobyname('tcp'); ($name,$aliases,$type,$len,$thisaddr)=gethostbyname($hostname); ($name,$aliases,$type,$len,$thataddr)=gethostbyname($BANKHOST); $thisport=pack($sockaddr, &AF_INET,0,$thisaddr); $thatport=pack($sockaddr, &AF_INET,$BANKPORT,$thataddr); socket(S, &PF_INET,&SOCK_STREAM,$proto) || die "cannot create socket\n"; bind(S,$thisport) || die "cannot bind socket\n"; connect(S,$thatport) || die "cannot connect socket\n"; select(S); $| = 1; # Turn on autoflushing select(stdout); $| = 1; # Select STDOUT as default output # # Build and send command # $REQUEST="COMMAND=$COMMAND AUTH=$AUTH"; chomp($CHECKSUM = `$QSUM "$REQUEST"`); $REQUEST .= " CHECKSUM=$CHECKSUM"; my $command=pack "a8 a1 A*",sprintf("%08d",length($REQUEST))," ",$REQUEST; print S "$command"; # Send Command to server @REPLY=(); while (<S>) { push(@REPLY,$_); } # Listen for Reply $STATUS=grep(/STATUSCODE=(\d*)/&&$1,@REPLY); # STATUSCODE stored in $STATUS grep(s/.*RESULT=//,@REPLY); # Parse out the RESULT return @REPLY; }

Header Processing (PERL code)

sysread(NS,$length,8); # Read length string sysread(NS,$delimiter,1); # Read delimiter byte $DEBUG && print STDERR "length=[$length]\tdelimiter=[$delimiter]\n"; while($length) { $DEBUG && print STDERR "Awaiting $length bytes -- ".`date`; $length-=sysread(NS,$request,$length); # Read request sleep 1; } %REQUEST=(); chomp($request); foreach (@REQUEST=&shellwords($request)) # Parse arguments into array { ($key,$value)=split(/=/,$_); $REQUEST{$key}=$value unless defined $REQUEST{$key}; } $request =~ s/\s+CHECKSUM=.*//; # Strip off the checksum print STDERR "REQUEST=$request\n"; chomp($checksum=`$QSUM "$request"`); $me=$REQUEST{AUTH}; $command=$REQUEST{COMMAND}; if (!grep($command eq $_,@VALIDCMDS)) { $REPLY = "STATUSCODE=0 RESULT=$command is not a valid command\n";} elsif ($checksum ne $REQUEST{CHECKSUM}) { $REPLY = "STATUSCODE=0 RESULT=Invalid Checksum\n";} else { $REPLY = do $command(@REQUEST); } $len=sprintf("%08d",length($REPLY)-1); $delim=' '; $DEBUG && print STDERR "REPLY=${len}${delim}$REPLY\n"; $buf="$len"."$delim"."$REPLY"; syswrite(NS,$buf,length($buf)); close NS;