From 0e4a26e3b4975f9237b08a772420c369d9f29b6c Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Mon, 29 Dec 2014 22:07:05 -0800 Subject: [PATCH] Add Diskattrmap, Scsiattrmap for probed scsi devices Additional changes - Use ``iota`` for constants - Remove unncessary C header files - ``new-cmd`` now depends on codegangsta cli --- cmd/new-cmd/.gitignore | 3 +- cmd/new-cmd/README.md | 8 +- cmd/new-cmd/minio-cli.go | 157 ---------------- cmd/new-cmd/new-cmd-flags.go | 98 ++++++++++ cmd/new-cmd/new-cmd.go | 102 +++++++++++ pkg/cpu/Makefile | 11 -- pkg/cpu/cpu.go | 4 +- pkg/cpu/cpu.h | 24 --- pkg/cpu/cpu_test.go | 2 + pkg/crypto/md5c/md5.c | 11 +- pkg/crypto/md5c/md5.h | 43 ----- pkg/crypto/md5c/md5c.go | 14 +- pkg/erasure/encode.go | 2 +- pkg/scsi/{constants.go => constants_linux.go} | 3 +- pkg/scsi/scsi.go | 96 ---------- pkg/scsi/scsi_linux.go | 170 ++++++++++++++++++ pkg/scsi/scsi_test.go | 3 + pkg/scsi/{utils.go => utils_linux.go} | 0 pkg/strbyteconv/strbyteconv.go | 11 +- 19 files changed, 414 insertions(+), 348 deletions(-) delete mode 100644 cmd/new-cmd/minio-cli.go create mode 100644 cmd/new-cmd/new-cmd-flags.go create mode 100644 cmd/new-cmd/new-cmd.go delete mode 100644 pkg/cpu/Makefile delete mode 100644 pkg/cpu/cpu.h delete mode 100644 pkg/crypto/md5c/md5.h rename pkg/scsi/{constants.go => constants_linux.go} (94%) delete mode 100644 pkg/scsi/scsi.go create mode 100644 pkg/scsi/scsi_linux.go rename pkg/scsi/{utils.go => utils_linux.go} (100%) diff --git a/cmd/new-cmd/.gitignore b/cmd/new-cmd/.gitignore index d9a86452a..16350cefc 100644 --- a/cmd/new-cmd/.gitignore +++ b/cmd/new-cmd/.gitignore @@ -1,2 +1 @@ -templates.go -minio-cli \ No newline at end of file +new-cmd diff --git a/cmd/new-cmd/README.md b/cmd/new-cmd/README.md index 657d796ec..e2cf2ae3d 100644 --- a/cmd/new-cmd/README.md +++ b/cmd/new-cmd/README.md @@ -1,6 +1,6 @@ ## Introduction -`minio-cli` is a stub builder for new commands,options on top of [codegangsta/cli](https://github.com/codegangsta/cli), +`new-cmd` is a stub builder for new commands,options on top of [codegangsta/cli](https://github.com/codegangsta/cli), Idea behind providing a simple tool for rapid prototyping and encouraging new contributors to the project @@ -9,17 +9,17 @@ Idea behind providing a simple tool for rapid prototyping and encouraging new co You just need to set its command name and options: ```bash -$ minio-cli -options option1,option2,option3 [command] +$ new-cmd --options option1,option2,option3 --usage "This command is best" [commandname] ``` -Generates three files namely [command].go, [command]-options.go, [command].md +Generates three files [commandname].go, [commandname]-options.go, [commandname].md respectively ## Example If you want to start to building `bucket` command which has options `get`, `put`, `list`: ```bash -$ minio-cli -options get,put,list bucket +$ new-cmd --options get,put,list --usage "Bucket operations" bucket $ ls bucket/ bucket-options.go bucket.go bucket.md ``` diff --git a/cmd/new-cmd/minio-cli.go b/cmd/new-cmd/minio-cli.go deleted file mode 100644 index 83432f8c6..000000000 --- a/cmd/new-cmd/minio-cli.go +++ /dev/null @@ -1,157 +0,0 @@ -package main - -import ( - "flag" - "log" - "os" - "path" - "strings" - "text/template" - "time" - - "github.com/minio-io/minio/pkg/utils" -) - -type source struct { - Name string - TempLate template.Template -} - -const ( - // Relative path from GOPATH default - TEMPLATEREPO = "/src/github.com/minio-io/minio/cmd/minio-cli/templates/" -) - -type option struct { - Name string - Definename string - Functionname string -} - -type command struct { - Name string - Usage string - Month string - Year int - Options []option -} - -func (f source) get(commandName string, definition command) error { - wr, err := os.Create(path.Join(commandName, f.Name)) - if err != nil { - return err - } - - defer wr.Close() - return f.TempLate.Execute(wr, definition) -} - -func initCommand(commandname, usage string, inputOptions []string) command { - year, month, _ := time.Now().Date() - return command{ - Name: commandname, - Usage: usage, - Month: month.String(), - Year: year, - Options: initOptions(inputOptions), - } -} - -func initOptions(inputOptions []string) []option { - var options []option - - if inputOptions[0] == "" { - return options - } - - for _, name := range inputOptions { - option := option{ - Name: name, - Definename: utils.FirstUpper(name), - Functionname: "do" + utils.FirstUpper(name), - } - options = append(options, option) - } - - return options -} - -func main() { - var flOptions, flUsage, flTemplatePath string - - flag.StringVar(&flOptions, "options", "", "Comma-separated list of options to build") - flag.StringVar(&flUsage, "usage", "", "A one liner explains the purpose of the cli being built") - flag.StringVar(&flTemplatePath, "templatepath", "", "Non standard templates path") - - flag.Parse() - - inputOptions := strings.Split(flOptions, ",") - - commandname := flag.Arg(0) - - if commandname == "" { - log.Fatal("command name must not be blank\n") - } - - if inputOptions[0] == "" { - log.Fatal("-options option1 should be specified with command name") - } - - gopath := os.Getenv("GOPATH") - - var mainTemplatePath, optionsTemplatePath, readmeTemplatePath string - if flTemplatePath == "" { - mainTemplatePath = path.Join(gopath, TEMPLATEREPO, "main.tmpl") - optionsTemplatePath = path.Join(gopath, TEMPLATEREPO, "options.tmpl") - readmeTemplatePath = path.Join(gopath, TEMPLATEREPO, "README.tmpl") - } else { - mainTemplatePath = path.Join(flTemplatePath, "main.tmpl") - optionsTemplatePath = path.Join(flTemplatePath, "options.tmpl") - readmeTemplatePath = path.Join(flTemplatePath, "README.tmpl") - } - - if _, err := os.Stat(mainTemplatePath); err != nil { - log.Fatal(err) - } - if _, err := os.Stat(optionsTemplatePath); err != nil { - log.Fatal(err) - } - if _, err := os.Stat(readmeTemplatePath); err != nil { - log.Fatal(err) - } - - var mainTemplate = template.Must(template.ParseFiles(mainTemplatePath)) - var optionsTemplate = template.Must(template.ParseFiles(optionsTemplatePath)) - var readmeTemplate = template.Must(template.ParseFiles(readmeTemplatePath)) - - err := os.Mkdir(commandname, 0755) - utils.Assert(err) - - command := initCommand(commandname, flUsage, inputOptions) - - optionsGo := source{ - Name: commandname + "-options.go", - TempLate: *optionsTemplate, - } - - readmeMd := source{ - Name: commandname + ".md", - TempLate: *readmeTemplate, - } - - mainGo := source{ - Name: commandname + ".go", - TempLate: *mainTemplate, - } - - err = readmeMd.get(commandname, command) - utils.Assert(err) - - mainGo.get(commandname, command) - utils.Assert(err) - - optionsGo.get(commandname, command) - - err = GoFormat(commandname) - utils.Assert(err) -} diff --git a/cmd/new-cmd/new-cmd-flags.go b/cmd/new-cmd/new-cmd-flags.go new file mode 100644 index 000000000..14d7e6afa --- /dev/null +++ b/cmd/new-cmd/new-cmd-flags.go @@ -0,0 +1,98 @@ +package main + +import ( + "log" + "os" + "path" + "strings" + "text/template" + + "github.com/codegangsta/cli" + "github.com/minio-io/minio/pkg/utils" +) + +func parseInput(c *cli.Context) { + var commandName string + switch len(c.Args()) { + case 1: + commandName = c.Args()[0] + default: + log.Fatal("command name must not be blank\n") + } + + var inputOptions []string + if c.String("options") != "" { + inputOptions = strings.Split(c.String("options"), ",") + } + + if inputOptions[0] == "" { + log.Fatal("options cannot be empty with a command name") + } + + var commandUsage string + if c.String("usage") != "" { + commandUsage = c.String("usage") + } + + var templatePath string + if c.String("path") != "" { + templatePath = c.String("path") + } + + gopath := os.Getenv("GOPATH") + + var mainTemplatePath, optionsTemplatePath, readmeTemplatePath string + if templatePath == TEMPLATEREPO { + mainTemplatePath = path.Join(gopath, templatePath, "main.tmpl") + optionsTemplatePath = path.Join(gopath, templatePath, "options.tmpl") + readmeTemplatePath = path.Join(gopath, templatePath, "README.tmpl") + } else { + mainTemplatePath = path.Join(templatePath, "main.tmpl") + optionsTemplatePath = path.Join(templatePath, "options.tmpl") + readmeTemplatePath = path.Join(templatePath, "README.tmpl") + } + if _, err := os.Stat(mainTemplatePath); err != nil { + log.Fatal(err) + } + if _, err := os.Stat(optionsTemplatePath); err != nil { + log.Fatal(err) + } + if _, err := os.Stat(readmeTemplatePath); err != nil { + log.Fatal(err) + } + + var mainTemplate = template.Must(template.ParseFiles(mainTemplatePath)) + var optionsTemplate = template.Must(template.ParseFiles(optionsTemplatePath)) + var readmeTemplate = template.Must(template.ParseFiles(readmeTemplatePath)) + + err := os.Mkdir(commandName, 0755) + utils.Assert(err) + + command := initCommand(commandName, commandUsage, inputOptions) + + optionsGo := source{ + Name: commandName + "-options.go", + TempLate: *optionsTemplate, + } + + readmeMd := source{ + Name: commandName + ".md", + TempLate: *readmeTemplate, + } + + mainGo := source{ + Name: commandName + ".go", + TempLate: *mainTemplate, + } + + err = readmeMd.get(commandName, command) + utils.Assert(err) + + mainGo.get(commandName, command) + utils.Assert(err) + + optionsGo.get(commandName, command) + + err = GoFormat(commandName) + utils.Assert(err) +} diff --git a/cmd/new-cmd/new-cmd.go b/cmd/new-cmd/new-cmd.go new file mode 100644 index 000000000..272eb94df --- /dev/null +++ b/cmd/new-cmd/new-cmd.go @@ -0,0 +1,102 @@ +package main + +import ( + "os" + "path" + "text/template" + "time" + + "github.com/codegangsta/cli" + "github.com/minio-io/minio/pkg/utils" +) + +type source struct { + Name string + TempLate template.Template +} + +const ( + // Relative path from GOPATH default + TEMPLATEREPO = "/src/github.com/minio-io/minio/cmd/new-cmd/templates/" +) + +type option struct { + Name string + Definename string + Functionname string +} + +type command struct { + Name string + Usage string + Month string + Year int + Options []option +} + +func (f source) get(commandName string, definition command) error { + wr, err := os.Create(path.Join(commandName, f.Name)) + if err != nil { + return err + } + + defer wr.Close() + return f.TempLate.Execute(wr, definition) +} + +func initCommand(commandname, usage string, inputOptions []string) command { + year, month, _ := time.Now().Date() + return command{ + Name: commandname, + Usage: usage, + Month: month.String(), + Year: year, + Options: initOptions(inputOptions), + } +} + +func initOptions(inputOptions []string) []option { + var options []option + + if inputOptions[0] == "" { + return options + } + + for _, name := range inputOptions { + option := option{ + Name: name, + Definename: utils.FirstUpper(name), + Functionname: "do" + utils.FirstUpper(name), + } + options = append(options, option) + } + + return options +} + +func main() { + app := cli.NewApp() + app.Name = "new-cmd" + app.Usage = "Is a stub builder for new commands, options" + var flags = []cli.Flag{ + cli.StringFlag{ + Name: "options", + Value: "", + Usage: "Command-separated list of options to build", + }, + cli.StringFlag{ + Name: "path", + Value: TEMPLATEREPO, + Usage: "Non standard templates path", + }, + cli.StringFlag{ + Name: "usage", + Value: "", + Usage: "A one liner explaining the new command being built", + }, + } + app.Flags = flags + app.Action = parseInput + app.Author = "Minio" + app.Run(os.Args) +} diff --git a/pkg/cpu/Makefile b/pkg/cpu/Makefile deleted file mode 100644 index fb6ac1387..000000000 --- a/pkg/cpu/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: build test -.PHONY: all - -build: - @godep go build - -test: build - @godep go test -race -coverprofile=cover.out - -clean: - @rm -v cover.out diff --git a/pkg/cpu/cpu.go b/pkg/cpu/cpu.go index bbe26da9f..d4c6ec588 100644 --- a/pkg/cpu/cpu.go +++ b/pkg/cpu/cpu.go @@ -18,7 +18,9 @@ package cpu -// #include "cpu.h" +// int has_sse41 (void); +// int has_avx (void); +// int has_avx2 (void); import "C" func HasSSE41() bool { diff --git a/pkg/cpu/cpu.h b/pkg/cpu/cpu.h deleted file mode 100644 index 5eb27e13c..000000000 --- a/pkg/cpu/cpu.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - */ - -#ifndef __CPU_H__ -#define __CPU_H__ - -int has_sse41 (void); -int has_avx (void); -int has_avx2 (void); - -#endif /* __CPU_H__ */ diff --git a/pkg/cpu/cpu_test.go b/pkg/cpu/cpu_test.go index 5126f2a31..5c2d889a0 100644 --- a/pkg/cpu/cpu_test.go +++ b/pkg/cpu/cpu_test.go @@ -14,6 +14,8 @@ * limitations under the License. */ +// +build amd64 + package cpu import ( diff --git a/pkg/crypto/md5c/md5.c b/pkg/crypto/md5c/md5.c index 43c945d4e..d270fa63d 100644 --- a/pkg/crypto/md5c/md5.c +++ b/pkg/crypto/md5c/md5.c @@ -36,7 +36,16 @@ */ #include -#include "md5.h" + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; /* * The basic MD5 functions. diff --git a/pkg/crypto/md5c/md5.h b/pkg/crypto/md5c/md5.h deleted file mode 100644 index 0553cd21f..000000000 --- a/pkg/crypto/md5c/md5.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. - * MD5 Message-Digest Algorithm (RFC 1321). - * - * Homepage: - * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 - * - * Author: - * Alexander Peslyak, better known as Solar Designer - * - * This software was written by Alexander Peslyak in 2001. No copyright is - * claimed, and the software is hereby placed in the public domain. - * In case this attempt to disclaim copyright and place the software in the - * public domain is deemed null and void, then the software is - * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the - * general public under the following terms: - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted. - * - * There's ABSOLUTELY NO WARRANTY, express or implied. - * - * See md5.c for more information. - */ - -#ifndef __MD5_H__ -#define __MD5_H__ - -/* Any 32-bit or wider unsigned integer data type will do */ -typedef unsigned int MD5_u32plus; - -typedef struct { - MD5_u32plus lo, hi; - MD5_u32plus a, b, c, d; - unsigned char buffer[64]; - MD5_u32plus block[16]; -} MD5_CTX; - -extern void MD5_Init(MD5_CTX *ctx); -extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); -extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); - -#endif /* __MD5_H__ */ diff --git a/pkg/crypto/md5c/md5c.go b/pkg/crypto/md5c/md5c.go index f79744461..91c64a38e 100644 --- a/pkg/crypto/md5c/md5c.go +++ b/pkg/crypto/md5c/md5c.go @@ -2,7 +2,19 @@ package md5c -// #include "md5.h" +// /* Any 32-bit or wider unsigned integer data type will do */ +// typedef unsigned int MD5_u32plus; +// +// typedef struct { +// MD5_u32plus lo, hi; +// MD5_u32plus a, b, c, d; +// unsigned char buffer[64]; +// MD5_u32plus block[16]; +// } MD5_CTX; +// +// void MD5_Init(MD5_CTX *ctx); +// void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +// void MD5_Final(unsigned char *result, MD5_CTX *ctx); import "C" import ( "io" diff --git a/pkg/erasure/encode.go b/pkg/erasure/encode.go index 611134311..0467e0eed 100644 --- a/pkg/erasure/encode.go +++ b/pkg/erasure/encode.go @@ -33,7 +33,7 @@ import ( const ( VANDERMONDE = iota - CAUCHY = iota + CAUCHY ) const ( diff --git a/pkg/scsi/constants.go b/pkg/scsi/constants_linux.go similarity index 94% rename from pkg/scsi/constants.go rename to pkg/scsi/constants_linux.go index 38ac6d79b..e8ac1eabd 100644 --- a/pkg/scsi/constants.go +++ b/pkg/scsi/constants_linux.go @@ -20,9 +20,8 @@ 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_BLOCK = "/sys/block/" SYSFS_CLASS_SCSI_DEVICES = "/sys/class/scsi_device/" UDEV = "/dev/" DEV_DISK_BYID_DIR = "/dev/disk/by-id" diff --git a/pkg/scsi/scsi.go b/pkg/scsi/scsi.go deleted file mode 100644 index d1684bd6f..000000000 --- a/pkg/scsi/scsi.go +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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/pkg/scsi/scsi_linux.go b/pkg/scsi/scsi_linux.go new file mode 100644 index 000000000..33bb68b11 --- /dev/null +++ b/pkg/scsi/scsi_linux.go @@ -0,0 +1,170 @@ +/* + * 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 { + Disk string + Scsiattrmap map[string][]byte + Diskattrmap map[string][]byte +} + +type Devices struct { + List []Scsi +} + +func (d *Devices) getInfo(disk string) (map[string][]byte, error) { + var diskAttrsList []string + var diskQueueAttrs []string + aggrAttrMap := make(map[string][]byte) + + sysfs_block_dev := path.Join(SYSFS_BLOCK + disk) + sysfs_block_dev_queue := path.Join(sysfs_block_dev + "/queue") + + scsiFiles, err := ioutil.ReadDir(sysfs_block_dev) + if err != nil { + return nil, err + } + + scsiQueueFiles, err := ioutil.ReadDir(sysfs_block_dev_queue) + if err != nil { + return nil, err + } + + for _, sf := range scsiFiles { + if sf.IsDir() { + continue + } + // Skip symlinks + if !sf.Mode().IsRegular() { + continue + } + // Skip, not readable, write-only + if sf.Mode().Perm() == 128 { + continue + } + diskAttrsList = append(diskAttrsList, sf.Name()) + } + + for _, sf := range scsiQueueFiles { + if sf.IsDir() { + continue + } + // Skip symlinks + if !sf.Mode().IsRegular() { + continue + } + // Skip, not readable, write-only + if sf.Mode().Perm() == 128 { + continue + } + diskQueueAttrs = append(diskQueueAttrs, sf.Name()) + } + + if len(diskAttrsList) == 0 { + return nil, errors.New("No disk attributes found") + } + + if len(diskQueueAttrs) == 0 { + return nil, errors.New("No disk queue attributes found") + } + + diskAttrMap := getattrs(sysfs_block_dev, diskAttrsList) + diskQueueAttrMap := getattrs(sysfs_block_dev_queue, diskQueueAttrs) + + for k, v := range diskAttrMap { + aggrAttrMap[k] = v + } + + for k, v := range diskQueueAttrMap { + aggrAttrMap[k] = v + } + + return aggrAttrMap, nil +} + +func (d *Devices) Get() error { + var scsidevices []string + var scsiAttrList []string + + sysFiles, err := ioutil.ReadDir(SYSFS_SCSI_DEVICES) + 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_DEVICES, scsi, "/") + scsiAttrs, err := ioutil.ReadDir(scsiAttrPath) + if err != nil { + return err + } + scsiBlockPath := path.Join(SYSFS_SCSI_DEVICES, scsi, "/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.Disk = 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.Scsiattrmap = attrMap + _scsi.Diskattrmap, err = d.getInfo(scsidevList[0].Name()) + if err != nil { + return err + } + d.List = append(d.List, _scsi) + } + return nil +} diff --git a/pkg/scsi/scsi_test.go b/pkg/scsi/scsi_test.go index b1017db87..6d0f29b97 100644 --- a/pkg/scsi/scsi_test.go +++ b/pkg/scsi/scsi_test.go @@ -17,4 +17,7 @@ func (s *MySuite) TestSCSI(c *C) { err := d.Get() c.Assert(err, IsNil) c.Assert(len(d.List), Equals, 1) + + c.Assert(len(d.List[0].Scsiattrmap), Not(Equals), 0) + c.Assert(len(d.List[0].Diskattrmap), Not(Equals), 0) } diff --git a/pkg/scsi/utils.go b/pkg/scsi/utils_linux.go similarity index 100% rename from pkg/scsi/utils.go rename to pkg/scsi/utils_linux.go diff --git a/pkg/strbyteconv/strbyteconv.go b/pkg/strbyteconv/strbyteconv.go index 58bd1d329..18aa7dd65 100644 --- a/pkg/strbyteconv/strbyteconv.go +++ b/pkg/strbyteconv/strbyteconv.go @@ -25,11 +25,12 @@ import ( ) const ( - UNIT_BYTE = 1 - UNIT_KILOBYTE = 1024 * UNIT_BYTE - UNIT_MEGABYTE = 1024 * UNIT_KILOBYTE - UNIT_GIGABYTE = 1024 * UNIT_MEGABYTE - UNIT_TERABYTE = 1024 * UNIT_GIGABYTE + UNIT_BYTE = 1 << (10 * iota) + UNIT_KILOBYTE + UNIT_MEGABYTE + UNIT_GIGABYTE + UNIT_TERABYTE + UNIT_PETABYTE ) func BytesToString(bytes uint64) string {