Files
mtx/mtx-1.3.12/contrib/mtx.py
2018-07-31 15:07:09 -05:00

307 lines
8.1 KiB
Python

# Copyright 2000 Enhanced Software Technologies Inc.
# Released under Free Software Foundation's General Public License,
# Version 2 or above
#
# This is an example of how to parse the 'mtx' output from a scripting
# language.
#
# Routine to call 'mtx' and read status, or
# whatever.
#
# We do this here rather than creating a Python "C" module because:
# 1) Reduces complexity of compile environment
# 2) Easier debugging.
# 3) More in keeping with the Unix philosophy of things.
# 4) Easier to add new functionality.
#
#
import string
import os
import time # we can do some waiting here...
def readpipe(command):
result=""
infile=os.popen(command,"r")
try:
s=infile.read()
except:
s=""
pass
if not s:
return None # didn't get anything :-(.
result=result+s
return result
# these are returned by the mtx.status routine:
class slotstatus:
def __init__(self,slotnum,middle,barcode=None):
middle=string.strip(middle)
try:
left,right=string.split(middle," ")
except:
left=middle
right=None
pass
# Note: We will not be able to test this at the moment since the
# 220 has no import/export port!
if right=="IMPORT/EXPORT":
self.importexport=1
else:
self.importexport=0
pass
self.slotnum=int(slotnum) # make sure it's an integer...
if left=="Full":
self.full=1
else:
self.full=None
pass
if not barcode:
self.voltag=None
else:
l=string.split(barcode,"=",1)
self.voltag=l[1]
pass
return
pass
# Drive status lines have this format:
#Data Transfer Element 0:Full (Storage Element 10 Loaded):VolumeTag = B0000009H
#Data Transfer Element 1:Empty
class drivestatus:
def __init__(self,slotnum,middle,barcode=None):
self.slotnum=slotnum
if middle=="Empty":
self.full=None
self.origin=None
self.voltag=None
return
else:
self.full=1
pass
# okay, we know we have a tape in the drive.
# split and find out our origin: we will always have
# an origin, even if the #$@% mtx program had to dig one
# out of the air:
l=string.split(middle," ")
self.origin=int(l[3])
if not barcode:
self.voltag=None # barcode of this element.
else:
l=string.split(barcode," ")
self.voltag=string.strip(l[2])
pass
return
pass
# This is the return value for mtx.status.
class mtxstatus:
def __init__(self):
self.numdrives=None
self.numslots=None
self.numexport=None
self.drives=[] # a list of drivestatus instances.
self.slots=[] # a list of slotstatus instances
self.export=[] # another list of slotstatus instances
return
pass
# call 'mtx' and get barcode info, if possible:
# okay, we now have a string that consists of a number of lines.
# we want to explode this string into its component parts.
# Example format:
# Storage Changer /dev/sgd:2 Drives, 21 Slots
# Data Transfer Element 0:Full (Storage Element '5' Loaded)
# Data Transfer Element 1:Empty
# Storage Element 1:Full :VolumeTag=CLNA0001
# Storage Element 2:Full :VolumeTag=B0000009
# Storage Element 3:Full :VolumeTag=B0000010
# ....
# What we want to do, then, is:
# 1) Turn it into lines by doing a string.split on newline.
# 2) Split the 1st line on ":" to get left and right.
# 3) Split the right half on space to get #drives "Drives," #slots
# 4) process the drives (Full,Empty, etc.)
# 5) For each of the remaining lines: Split on ':'
# 6) Full/Empty status is in 2)
#
configdir="/opt/brupro/bin" # sigh.
def status(device):
retval=mtxstatus()
command="%s/mtx -f %s status" % (configdir,device)
result=readpipe(command)
if not result:
return None # sorry!
# now to parse:
try:
lines=string.split(result,"\n")
except:
return None # sorry, no status!
# print "DEBUG:lines=",lines
try:
l=string.split(lines[0],":")
except:
return None # sorry, no status!
# print "DEBUG:l=",l
leftside=l[0]
rightside=l[1]
if len(l) > 2:
barcode=l[3]
else:
barcode=None
pass
t=string.split(rightside)
retval.numdrives=int(t[0])
retval.numslots=int(t[2])
for s in lines[1:]:
if not s:
continue # skip blank lines!
#print "DEBUG:s=",s
parts=string.split(s,":")
leftpart=string.split(parts[0])
rightpart=parts[1]
try:
barcode=parts[2]
except:
barcode=None
pass
#print "DEBUG:leftpart=",leftpart
if leftpart[0]=="Data" and leftpart[1]=="Transfer":
retval.drives.append(drivestatus(leftpart[3],rightpart,barcode))
pass
if leftpart[0]=="Storage" and leftpart[1]=="Element":
element=slotstatus(leftpart[2],rightpart,barcode)
if element.importexport:
retval.export.append(element)
else:
retval.slots.append(element)
pass
pass
continue
return retval
# Output of a mtx inquiry looks like:
#
#Product Type: Medium Changer
#Vendor ID: 'EXABYTE '
#Product ID: 'Exabyte EZ17 '
#Revision: '1.07'
#Attached Changer: No
#
# We simply return a hash table with these values { left:right } format.
def mtxinquiry(device):
command="%s/mtx -f %s inquiry" % (configdir,device)
str=readpipe(command) # calls the command, returns all its data.
str=string.strip(str)
lines=string.split(str,"\n")
retval={}
for l in lines:
# DEBUG #
l=string.strip(l)
print "splitting line: '",l,"'"
idx,val=string.split(l,':',1)
val=string.strip(val)
if val[0]=="'":
val=val[1:-1] # strip off single quotes, sigh.
pass
retval[idx]=val
continue
return retval
# Now for the easy part:
def load(device,slot,drive=0):
command="%s/mtx -f %s load %s %s >/dev/null " % (configdir,device,slot,drive)
status=os.system(command)
return status
def unload(device,slot,drive=0):
command="%s/mtx -f %s unload %s %s >/dev/null " % (configdir,device,slot,drive)
return os.system(command)
def inventory(device):
command="%s/mtx -f %s inventory >/dev/null " % (configdir,device)
return os.system(command)
def wait_for_inventory(device):
# loop while we have an error return...
errcount=0
while inventory(device):
if errcount==0:
print "Waiting for loader '%s'" % device
pass
time.sleep(1)
try:
s=status(device)
except:
s=None
pass
if s:
return 0 # well, whatever we're doing, we're inventoried :-(
errcount=errcount+1
if errcount==600: # we've been waiting for 10 minutes :-(
return 1 # sorry!
continue
return 0 # we succeeded!
# RCS REVISION LOG:
# $Log$
# Revision 1.1 2001/06/05 17:10:51 elgreen
# Initial revision
#
# Revision 1.2 2000/12/22 14:17:19 eric
# mtx 1.2.11pre1
#
# Revision 1.14 2000/11/12 20:35:29 eric
# do string.strip on the voltag
#
# Revision 1.13 2000/11/04 00:33:38 eric
# if we can get an inventory on the loader after we send it 'mtx inventory',
# then obviously we managed to do SOMETHING.
#
# Revision 1.12 2000/10/28 00:04:34 eric
# added wait_for_inventory command
#
# Revision 1.11 2000/10/27 23:27:58 eric
# Added inventory command...
#
# Revision 1.10 2000/10/01 01:06:29 eric
# evening checkin
#
# Revision 1.9 2000/09/29 02:49:29 eric
# evening checkin
#
# Revision 1.8 2000/09/02 01:05:33 eric
# Evening Checkin
#
# Revision 1.7 2000/09/01 00:08:11 eric
# strip lines in mtxinquiry
#
# Revision 1.6 2000/09/01 00:05:33 eric
# debugging
#
# Revision 1.5 2000/08/31 23:46:01 eric
# fix def:
#
# Revision 1.4 2000/08/31 23:44:06 eric
# =->==
#