From e758cec43abdcd67952c30f0b42b16872e9d0484 Mon Sep 17 00:00:00 2001 From: Markus Rosjat Date: Sun, 14 Sep 2014 23:40:17 +0200 Subject: [PATCH] open new branch restructure_and_doc --- scsi.py | 18 ----- scsi_command.py | 23 ------ scsi_device.py | 15 ---- setup.py | 8 ++- sgio/__init__.py | 7 ++ sgio/pyscsi/__init__.py | 2 + sgio/pyscsi/scsi.py | 46 ++++++++++++ .../pyscsi/scsi_cdb_inquiry.py | 41 ++++++++++- sgio/pyscsi/scsi_command.py | 70 +++++++++++++++++++ sgio/pyscsi/scsi_device.py | 49 +++++++++++++ scsi_sense.py => sgio/pyscsi/scsi_sense.py | 47 +++++++++++-- sgiomodule.c => sgio/sgiomodule.c | 23 +++++- sgio/tests/__init__.py | 2 + test.py => sgio/tests/test_inquiry.py | 14 ++-- 14 files changed, 291 insertions(+), 74 deletions(-) delete mode 100644 scsi.py delete mode 100644 scsi_command.py delete mode 100644 scsi_device.py create mode 100644 sgio/__init__.py create mode 100644 sgio/pyscsi/__init__.py create mode 100644 sgio/pyscsi/scsi.py rename scsi_cdb_inquiry.py => sgio/pyscsi/scsi_cdb_inquiry.py (74%) create mode 100644 sgio/pyscsi/scsi_command.py create mode 100644 sgio/pyscsi/scsi_device.py rename scsi_sense.py => sgio/pyscsi/scsi_sense.py (51%) rename sgiomodule.c => sgio/sgiomodule.c (76%) create mode 100644 sgio/tests/__init__.py rename test.py => sgio/tests/test_inquiry.py (53%) diff --git a/scsi.py b/scsi.py deleted file mode 100644 index 32bc727..0000000 --- a/scsi.py +++ /dev/null @@ -1,18 +0,0 @@ -from scsi_device import SCSIDevice -from scsi_command import SCSICommand -from scsi_cdb_inquiry import Inquiry - -SCSI_STATUS_GOOD = 0x00 -SCSI_STATUS_CHECK_CONDITION = 0x02 -SCSI_STATUS_CONDITIONS_MET = 0x04 -SCSI_STATUS_BUSY = 0x08 -SCSI_STATUS_RESERVATION_CONFLICT = 0x18 -SCSI_STATUS_TASK_SET_FULL = 0x28 -SCSI_STATUS_ACA_ACTIVE = 0x30 -SCSI_STATUS_TASK_ABORTED = 0x40 -SCSI_STATUS_SGIO_ERROR = 0xff - -class SCSI(SCSIDevice): - def Inquiry(self, evpd = 0, page_code = 0, alloc_len = 96): - return Inquiry(self, evpd, page_code, alloc_len) - diff --git a/scsi_command.py b/scsi_command.py deleted file mode 100644 index 47fdadf..0000000 --- a/scsi_command.py +++ /dev/null @@ -1,23 +0,0 @@ -class SCSICommand: - def __init__(self, dev, dataout_alloclen, datain_alloclen): - self.dev = dev - self.sense = bytearray(32) - self.dataout = bytearray(dataout_alloclen) - self.datain = bytearray(datain_alloclen) - self._result = {} - - def execute(self): - self.dev.execute(self.cdb, self.dataout, - self.datain, self.sense) - self.unmarshall() - - @property - def result(self): - return self._result - - @result.setter - def result(self, value): - self._result = value - - def add_result(self, key, value): - self.result.update({key:value}) diff --git a/scsi_device.py b/scsi_device.py deleted file mode 100644 index a23a56b..0000000 --- a/scsi_device.py +++ /dev/null @@ -1,15 +0,0 @@ -import scsi -import scsi_sense -import sgio - -class SCSIDevice: - def __init__(self, device): - self._fd = sgio.open(device) - - def execute(self, cdb, dataout, datain, sense): - status = sgio.execute(self._fd, cdb, dataout, datain, sense) - if status == scsi.SCSI_STATUS_CHECK_CONDITION: - raise scsi_sense.SCSICheckCondition(sense) - if status == scsi.SCSI_STATUS_SGIO_ERROR: - raise scsi_sense.SCSISGIOError() - diff --git a/setup.py b/setup.py index eac5d4d..5a86cb1 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,12 @@ -from distutils.core import setup, Extension +# coding: utf-8 -module1 = Extension('sgio', - sources = ['sgiomodule.c']) +from distutils.core import setup, Extension +module1 = Extension('sgio.sgio', + sources = ['sgio/sgiomodule.c']) setup (name = 'SGIO', version = '1.0', description = 'Module for calling ioctl(SG_IO)', + packages=['sgio','sgio.pyscsi','sgio.tests'], ext_modules = [module1]) diff --git a/sgio/__init__.py b/sgio/__init__.py new file mode 100644 index 0000000..ce300ce --- /dev/null +++ b/sgio/__init__.py @@ -0,0 +1,7 @@ +# coding: utf-8 + +from pyscsi import * +from tests import * +from sgio import open,close, execute + +__author__ = 'mr' diff --git a/sgio/pyscsi/__init__.py b/sgio/pyscsi/__init__.py new file mode 100644 index 0000000..9707519 --- /dev/null +++ b/sgio/pyscsi/__init__.py @@ -0,0 +1,2 @@ +__all_=['scsi','scsi_cdb_inquiry','scsi_command', 'scsi_device', 'scsi_sense'] +__author__ = 'mr' diff --git a/sgio/pyscsi/scsi.py b/sgio/pyscsi/scsi.py new file mode 100644 index 0000000..13bfd93 --- /dev/null +++ b/sgio/pyscsi/scsi.py @@ -0,0 +1,46 @@ +# coding: utf-8 + + +# Copyright (C) 2014 by Ronnie Sahlberg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +from scsi_device import SCSIDevice + +from scsi_cdb_inquiry import Inquiry + +SCSI_STATUS_GOOD = 0x00 +SCSI_STATUS_CHECK_CONDITION = 0x02 +SCSI_STATUS_CONDITIONS_MET = 0x04 +SCSI_STATUS_BUSY = 0x08 +SCSI_STATUS_RESERVATION_CONFLICT = 0x18 +SCSI_STATUS_TASK_SET_FULL = 0x28 +SCSI_STATUS_ACA_ACTIVE = 0x30 +SCSI_STATUS_TASK_ABORTED = 0x40 +SCSI_STATUS_SGIO_ERROR = 0xff + +class SCSI(SCSIDevice): + ''' + + ''' + def Inquiry(self, evpd = 0, page_code = 0, alloc_len = 96): + ''' + + :param evpd: + :param page_code: + :param alloc_len: + :return: + ''' + return Inquiry(self, evpd, page_code, alloc_len) + diff --git a/scsi_cdb_inquiry.py b/sgio/pyscsi/scsi_cdb_inquiry.py similarity index 74% rename from scsi_cdb_inquiry.py rename to sgio/pyscsi/scsi_cdb_inquiry.py index b0e440d..6d4a689 100644 --- a/scsi_cdb_inquiry.py +++ b/sgio/pyscsi/scsi_cdb_inquiry.py @@ -1,4 +1,21 @@ -import sys +# coding: utf-8 + + +# Copyright (C) 2014 by Ronnie Sahlberg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + from scsi_command import SCSICommand # @@ -13,7 +30,18 @@ DEVICE_IDENTIFICATION = 0x83 class Inquiry(SCSICommand): + ''' + + ''' def __init__(self, dev, evpd = 0, page_code = 0, alloclen = 96): + ''' + + :param dev: + :param evpd: + :param page_code: + :param alloclen: + :return: + ''' self._evpd = evpd self._page_code = page_code SCSICommand.__init__(self, dev, 0, alloclen) @@ -21,6 +49,13 @@ def __init__(self, dev, evpd = 0, page_code = 0, alloclen = 96): self.execute() def build_cdb(self, evpd, page_code, alloclen ): + ''' + + :param evpd: + :param page_code: + :param alloclen: + :return: + ''' cdb = bytearray([SCSI_CDB_INQUIRY, 0x00, 0x00, 0x00, 0x00, 0x00]) if (evpd): cdb[1] |= 0x01 @@ -30,6 +65,10 @@ def build_cdb(self, evpd, page_code, alloclen ): return cdb def unmarshall(self): + ''' + + :return: + ''' if self._evpd == 0: self.add_result('peripheral_qualifier', self.datain[0] >> 5) self.add_result('peripheral_qualifier', self.datain[0] >> 5) diff --git a/sgio/pyscsi/scsi_command.py b/sgio/pyscsi/scsi_command.py new file mode 100644 index 0000000..f0c583f --- /dev/null +++ b/sgio/pyscsi/scsi_command.py @@ -0,0 +1,70 @@ +# coding: utf-8 + + +# Copyright (C) 2014 by Ronnie Sahlberg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +class SCSICommand: + ''' + + ''' + def __init__(self, dev, dataout_alloclen, datain_alloclen): + ''' + + :param dev: + :param dataout_alloclen: + :param datain_alloclen: + :return: + ''' + self.dev = dev + self.sense = bytearray(32) + self.dataout = bytearray(dataout_alloclen) + self.datain = bytearray(datain_alloclen) + self._result = {} + + def execute(self): + ''' + + :return: + ''' + self.dev.execute(self.cdb, self.dataout, + self.datain, self.sense) + self.unmarshall() + + @property + def result(self): + ''' + + :return: + ''' + return self._result + + @result.setter + def result(self, value): + ''' + + :param value: + :return: + ''' + self._result = value + + def add_result(self, key, value): + ''' + + :param key: + :param value: + :return: + ''' + self.result.update({key:value}) diff --git a/sgio/pyscsi/scsi_device.py b/sgio/pyscsi/scsi_device.py new file mode 100644 index 0000000..02038f3 --- /dev/null +++ b/sgio/pyscsi/scsi_device.py @@ -0,0 +1,49 @@ +# coding: utf-8 + + +# Copyright (C) 2014 by Ronnie Sahlberg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +import scsi +import scsi_sense +import sgio + +class SCSIDevice: + ''' + + ''' + def __init__(self, device): + ''' + + :param device: + :return: + ''' + self._fd = sgio.open(device) + + def execute(self, cdb, dataout, datain, sense): + ''' + + :param cdb: + :param dataout: + :param datain: + :param sense: + :return: + ''' + status = sgio.execute(self._fd, cdb, dataout, datain, sense) + if status == scsi.SCSI_STATUS_CHECK_CONDITION: + raise scsi_sense.SCSICheckCondition(sense) + if status == scsi.SCSI_STATUS_SGIO_ERROR: + raise scsi_sense.SCSISGIOError() + diff --git a/scsi_sense.py b/sgio/pyscsi/scsi_sense.py similarity index 51% rename from scsi_sense.py rename to sgio/pyscsi/scsi_sense.py index 80cbfa8..e868ed3 100644 --- a/scsi_sense.py +++ b/sgio/pyscsi/scsi_sense.py @@ -1,3 +1,20 @@ +# coding: utf-8 + +# Copyright (C) 2014 by Ronnie Sahlberg +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + # # SPC4 4.6 Sense Data # @@ -6,14 +23,24 @@ SENSE_FORMAT_CURRENT_DESCRIPTOR = 0x72 SENSE_FORMAT_DEFERRED_DESCRIPTOR = 0x73 -sense_key_dict = { 0x00: 'No Sense', 0x01: 'Recovered Error', - 0x02: 'Not Ready', 0x03: 'Medium Error', - 0x04: 'Hardware Error', 0x05: 'Illegal Request', - 0x06: 'Unit Attention', 0x07: 'Data Protect', - 0x08: 'Blank Check', 0x09: 'Vendor Specific', - 0x0a: 'Copy Aborted', 0x0b: 'Aborted Command', - 0x0d: 'Volume Overflow', 0x0e: 'Miscompare', +# dict with common key code qualifiers +sense_key_dict = { 0x00: 'No Sense', + 0x01: 'Recovered Error', + 0x02: 'Not Ready', + 0x03: 'Medium Error', + 0x04: 'Hardware Error', + 0x05: 'Illegal Request', + 0x06: 'Unit Attention', + 0x07: 'Data Protect', + 0x08: 'Blank Check', + 0x09: 'Vendor Specific', + 0x0a: 'Copy Aborted', + 0x0b: 'Aborted Command', + 0x0d: 'Volume Overflow', + 0x0e: 'Miscompare', 0x0f: 'Completed'} + +# dict with additional sense data sense_ascq_dict = { 0x2400: 'Invalid Field In CDB', 0x2401: 'CDB Decryption Error', 0x2404: 'Security Audit Value Frozen', @@ -23,7 +50,13 @@ 0x2408: 'Invalid XCDB' } +# Exception Class for a SCSI REQUEST SENSE command class SCSICheckCondition(Exception): + '''Exception raised for errors in the SCSIDevice execute method + + Attributes: + sense -- bytearray with additional data + ''' def __init__(self, sense): self.valid = sense[0] & 0x80 self.response_code = sense[0] & 0x7f diff --git a/sgiomodule.c b/sgio/sgiomodule.c similarity index 76% rename from sgiomodule.c rename to sgio/sgiomodule.c index 5b63c88..7b7988b 100644 --- a/sgiomodule.c +++ b/sgio/sgiomodule.c @@ -1,3 +1,20 @@ +/* + Copyright (C) 2014 by Ronnie Sahlberg + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, see . +*/ + #include #include #include @@ -84,9 +101,9 @@ sgio_execute(PyObject *self, PyObject *args) if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { if (io_hdr.sb_len_wr > 0) - return Py_BuildValue("i", SCSI_STATUS_CHECK_CONDITION); + return Py_BuildValue("i", SCSI_STATUS_CHECK_CONDITION); - return Py_BuildValue("i", SCSI_STATUS_SGIO_ERROR); + return Py_BuildValue("i", SCSI_STATUS_SGIO_ERROR); } return Py_BuildValue("i", SCSI_STATUS_GOOD); @@ -98,7 +115,7 @@ sgio_close(PyObject *self, PyObject *args) int s; if (!PyArg_ParseTuple(args, "i", &s)) { - PyErr_SetString(SGIOError, "Wrong number of rguments to sgio_close"); + PyErr_SetString(SGIOError, "Wrong number of arguments to sgio_close"); return NULL; } diff --git a/sgio/tests/__init__.py b/sgio/tests/__init__.py new file mode 100644 index 0000000..e558988 --- /dev/null +++ b/sgio/tests/__init__.py @@ -0,0 +1,2 @@ +__all__=['test_inquiry'] +__author__ = 'mr' diff --git a/test.py b/sgio/tests/test_inquiry.py similarity index 53% rename from test.py rename to sgio/tests/test_inquiry.py index 367682b..5414deb 100755 --- a/test.py +++ b/sgio/tests/test_inquiry.py @@ -1,10 +1,13 @@ #!/usr/bin/env python +# coding: utf-8 + import sys -from scsi import SCSI -import scsi_cdb_inquiry as INQUIRY -if __name__ == "__main__": - s = SCSI(sys.argv[1]) +from sgio.pyscsi.scsi import SCSI +from sgio.pyscsi import scsi_cdb_inquiry as INQUIRY + +def main(device): + s = SCSI(device) i = s.Inquiry().result print i @@ -12,3 +15,6 @@ i = s.Inquiry(evpd = 1, page_code = INQUIRY.SUPPORTED_VPD_PAGES).result print i +if __name__ == "__main__": + main(sys.argv[1]) +