def load_drive(self, slot, drive=0): """ Loads the disk from the specified slot into the specified drive (default drive is 0) """ try: sh.mtx('-f', self.changer, 'altres', 'load', slot, drive) except sh.ErrorReturnCode_1: raise DriveAlreadyLoaded()
def unload_drive(self, slot=None, drive=0): """ Unloads the disc from the specified drive (default 0) into the specified slot, or the slot slot that the disc originally came from if unspecified """ try: if slot is None: sh.mtx('-f', self.changer, 'altres', 'unload') else: sh.mtx('-f', self.changer, 'altres', 'unload', slot) except sh.ErrorReturnCode_1: raise FailedToUnloadDrive()
def eject(self, slot): """ Causes the changer to unload the disk from the specified slot and eject it from the changer """ ejected = False try: sh.mtx('-f', self.changer, 'altres', 'eepos', '0', 'transfer', slot, self.ioslot) ejected = True self.status[slot]['full'] = False except sh.ErrorReturnCode_1: pass return ejected
def update_status(self): rawstatus = sh.mtx('-f', self.changer, "altres", "status").split("\n") mtxregexstring = "Storage Element (?P<number>[0-9]*)(?P<io> IMPORT/EXPORT|):" mtxregexstring += "(?P<state>Empty|Full).*" mtxregex = re.compile(mtxregexstring) for line in rawstatus: parseresult = mtxregex.match(line.strip()) if parseresult is not None: status = parseresult.groupdict() # If this is our import/export slot, make note of it if status['io'] != "": self.ioslot = status['number'] # If this is our first run and we're just learning about the different elements elif status['number'] not in self.status: self.status[status['number']] = {} self.status[status['number']]['full'] = status['state'] == "Full" # If we previously believed this to be in a different state than it is, then our # information about what's in there is probably wrong elif 'state' in self.status[status['number']]: if status['state'] != self.status[status['number']]['state']: self.status[status['number']] = {} self.status[status['number']]['full'] = status['state'] == "Full" return self.status
def load(self, slot=None): """ Causes the changer to accept a disk and load it into the specified slot. If no slot is specified, it selects an empty slot (update_status() must have been run already). Returns the slot the disk was inserted into """ if self.ioslot is None: raise NeverScannedError() if slot is None: for possible in self.status: if self.status[possible]['full'] is False: slot = possible if slot is None: # No slots available to load stuff into raise NoSlotsAvailableError() try: sh.mtx('-f', self.changer, 'altres', 'eepos', '0', 'transfer', self.ioslot, slot) self.status[slot]['full'] = True return slot except sh.ErrorReturnCode_1: return False
# sanity check; all tapes should be 8 chars and end in M8 if len(tapes) != len([k for k in tapes if k.endswith("M8") and len(k) == 8]): print(f"Got arguments: {tapes}.") print("All tape IDs should be 8 characters long and end in M8.") sys.exit(1) # no repeated tapes allowed if len(tapes) != len(set(tapes)): print("You may not repeat the same tape ID more than once.") sys.exit(1) # check if we have 4 empty mailslots raw_slots = mtx("-f", tape_device, "status") empty_mailslots = [ k for k in raw_slots.split("\n") if "IMPORT/EXPORT:Empty" in k ] if len(empty_mailslots) != 4: print(f"Need 4 empty mailslots; found {len(empty_mailslots)}.") sys.exit(1) mailslots = list( map(lambda sub: "".join([ele for ele in sub if ele.isnumeric()]), empty_mailslots)) # now we need to figure out which slots are which tapes