From e5953acf4b70529c4bbca95536c855a5a8650171 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Wed, 17 Dec 2014 03:10:48 -0800 Subject: [PATCH] Add linux scsi disk detection and attribute mapping --- pkgs/scsi/.gitignore | 1 + pkgs/scsi/constants.go | 64 ++++++++++++++++++++++++++++ pkgs/scsi/scsi.go | 96 ++++++++++++++++++++++++++++++++++++++++++ pkgs/scsi/scsi_test.go | 20 +++++++++ pkgs/scsi/utils.go | 48 +++++++++++++++++++++ 5 files changed, 229 insertions(+) create mode 100644 pkgs/scsi/.gitignore create mode 100644 pkgs/scsi/constants.go create mode 100644 pkgs/scsi/scsi.go create mode 100644 pkgs/scsi/scsi_test.go create mode 100644 pkgs/scsi/utils.go diff --git a/pkgs/scsi/.gitignore b/pkgs/scsi/.gitignore new file mode 100644 index 000000000..e810a59ed --- /dev/null +++ b/pkgs/scsi/.gitignore @@ -0,0 +1 @@ +scsi \ No newline at end of file diff --git a/pkgs/scsi/constants.go b/pkgs/scsi/constants.go new file mode 100644 index 000000000..38ac6d79b --- /dev/null +++ b/pkgs/scsi/constants.go @@ -0,0 +1,64 @@ +/* + * Mini Object Storage, (C) 2014 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// !build linux,amd64 + +package scsi + +var ( + // From 2.6.x kernel onwards, no need to support procfs + SYSFSROOT = "/sys" + SYSFS_SCSI_DEVICES = "/sys/bus/scsi/devices/" + SYSFS_BLOCK = "/block/" + SYSFS_CLASS_SCSI_DEVICES = "/sys/class/scsi_device/" + UDEV = "/dev/" + DEV_DISK_BYID_DIR = "/dev/disk/by-id" +) + +var SCSI_DEVICE_TYPES = []string{ + "disk", + "tape", + "printer", + "process", + "worm", + "cd/dvd", + "scanner", + "optical", + "mediumx", + "comms", + "(0xa)", + "(0xb)", + "storage", + "enclosu", + "sim disk", + "optical rd", + "bridge", + "osd", + "adi", + "sec man", + "zbc", + "(0x15)", + "(0x16)", + "(0x17)", + "(0x18)", + "(0x19)", + "(0x1a)", + "(0x1b)", + "(0x1c)", + "(0x1e)", + "wlun", + "no dev", +} diff --git a/pkgs/scsi/scsi.go b/pkgs/scsi/scsi.go new file mode 100644 index 000000000..d1684bd6f --- /dev/null +++ b/pkgs/scsi/scsi.go @@ -0,0 +1,96 @@ +/* + * Mini Object Storage, (C) 2014 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// !build linux,amd64 + +package scsi + +import ( + "errors" + "io/ioutil" + "path" +) + +// NOTE : supporting virtio based scsi devices +// is out of scope for this implementation + +type _Scsi struct { + device string + attrMap map[string][]byte +} + +type Devices struct { + List []_Scsi +} + +func (d *Devices) Get() error { + var scsidevices []string + var scsiAttrList []string + + sysfs := path.Join(SYSFS_SCSI_DEVICES) + sysFiles, err := ioutil.ReadDir(sysfs) + if err != nil { + return err + } + + scsidevices = filterdevices(sysFiles) + if len(scsidevices) == 0 { + return errors.New("No scsi devices found on the system") + } + + for _, scsi := range scsidevices { + var _scsi _Scsi + scsiAttrPath := path.Join(sysfs, scsi, "/") + scsiAttrs, err := ioutil.ReadDir(scsiAttrPath) + if err != nil { + return err + } + scsiBlockPath := path.Join(sysfs, scsi, SYSFS_BLOCK) + scsidevList, err := ioutil.ReadDir(scsiBlockPath) + if err != nil { + return err + } + + if len(scsidevList) > 1 { + return errors.New("Scsi address points to multiple block devices") + } + + _scsi.device = UDEV + scsidevList[0].Name() + for _, sa := range scsiAttrs { + // Skip directories + if sa.IsDir() { + continue + } + // Skip symlinks + if !sa.Mode().IsRegular() { + continue + } + // Skip, not readable, write-only + if sa.Mode().Perm() == 128 { + continue + } + scsiAttrList = append(scsiAttrList, sa.Name()) + } + + if len(scsiAttrList) == 0 { + return errors.New("No scsi attributes found") + } + attrMap := getattrs(scsiAttrPath, scsiAttrList) + _scsi.attrMap = attrMap + d.List = append(d.List, _scsi) + } + return nil +} diff --git a/pkgs/scsi/scsi_test.go b/pkgs/scsi/scsi_test.go new file mode 100644 index 000000000..b1017db87 --- /dev/null +++ b/pkgs/scsi/scsi_test.go @@ -0,0 +1,20 @@ +// !build linux,amd64 +package scsi + +import ( + . "gopkg.in/check.v1" + "testing" +) + +type MySuite struct{} + +var _ = Suite(&MySuite{}) + +func Test(t *testing.T) { TestingT(t) } + +func (s *MySuite) TestSCSI(c *C) { + var d Devices + err := d.Get() + c.Assert(err, IsNil) + c.Assert(len(d.List), Equals, 1) +} diff --git a/pkgs/scsi/utils.go b/pkgs/scsi/utils.go new file mode 100644 index 000000000..19cc04c2c --- /dev/null +++ b/pkgs/scsi/utils.go @@ -0,0 +1,48 @@ +/* + * Mini Object Storage, (C) 2014 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// !build linux,amd64 + +package scsi + +import ( + "io/ioutil" + "os" + "path" + "strings" +) + +func getattrs(scsiAttrPath string, scsiAttrList []string) map[string][]byte { + attrMap := make(map[string][]byte) + for _, attr := range scsiAttrList { + value, _ := ioutil.ReadFile(path.Join(scsiAttrPath, attr)) + attrMap[attr] = value + } + return attrMap +} + +func filterdevices(files []os.FileInfo) (scsidevices []string) { + for _, fi := range files { + if strings.Contains(fi.Name(), "host") { + continue + } + if strings.Contains(fi.Name(), "target") { + continue + } + scsidevices = append(scsidevices, fi.Name()) + } + return scsidevices +}