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
This commit is contained in:
Harshavardhana 2014-12-29 22:07:05 -08:00
parent 460fd63f05
commit 0e4a26e3b4
19 changed files with 414 additions and 348 deletions

View File

@ -1,2 +1 @@
templates.go new-cmd
minio-cli

View File

@ -1,6 +1,6 @@
## Introduction ## 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 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: You just need to set its command name and options:
```bash ```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 ## Example
If you want to start to building `bucket` command which has options `get`, `put`, `list`: If you want to start to building `bucket` command which has options `get`, `put`, `list`:
```bash ```bash
$ minio-cli -options get,put,list bucket $ new-cmd --options get,put,list --usage "Bucket operations" bucket
$ ls bucket/ $ ls bucket/
bucket-options.go bucket.go bucket.md bucket-options.go bucket.go bucket.md
``` ```

View File

@ -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)
}

View File

@ -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)
}

102
cmd/new-cmd/new-cmd.go Normal file
View File

@ -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)
}

View File

@ -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

View File

@ -18,7 +18,9 @@
package cpu package cpu
// #include "cpu.h" // int has_sse41 (void);
// int has_avx (void);
// int has_avx2 (void);
import "C" import "C"
func HasSSE41() bool { func HasSSE41() bool {

View File

@ -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__ */

View File

@ -14,6 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
// +build amd64
package cpu package cpu
import ( import (

View File

@ -36,7 +36,16 @@
*/ */
#include <string.h> #include <string.h>
#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. * The basic MD5 functions.

View File

@ -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 <solar at openwall.com>
*
* 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__ */

View File

@ -2,7 +2,19 @@
package md5c 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 "C"
import ( import (
"io" "io"

View File

@ -33,7 +33,7 @@ import (
const ( const (
VANDERMONDE = iota VANDERMONDE = iota
CAUCHY = iota CAUCHY
) )
const ( const (

View File

@ -20,9 +20,8 @@ package scsi
var ( var (
// From 2.6.x kernel onwards, no need to support procfs // From 2.6.x kernel onwards, no need to support procfs
SYSFSROOT = "/sys"
SYSFS_SCSI_DEVICES = "/sys/bus/scsi/devices/" SYSFS_SCSI_DEVICES = "/sys/bus/scsi/devices/"
SYSFS_BLOCK = "/block/" SYSFS_BLOCK = "/sys/block/"
SYSFS_CLASS_SCSI_DEVICES = "/sys/class/scsi_device/" SYSFS_CLASS_SCSI_DEVICES = "/sys/class/scsi_device/"
UDEV = "/dev/" UDEV = "/dev/"
DEV_DISK_BYID_DIR = "/dev/disk/by-id" DEV_DISK_BYID_DIR = "/dev/disk/by-id"

View File

@ -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
}

170
pkg/scsi/scsi_linux.go Normal file
View File

@ -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
}

View File

@ -17,4 +17,7 @@ func (s *MySuite) TestSCSI(c *C) {
err := d.Get() err := d.Get()
c.Assert(err, IsNil) c.Assert(err, IsNil)
c.Assert(len(d.List), Equals, 1) 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)
} }

View File

@ -25,11 +25,12 @@ import (
) )
const ( const (
UNIT_BYTE = 1 UNIT_BYTE = 1 << (10 * iota)
UNIT_KILOBYTE = 1024 * UNIT_BYTE UNIT_KILOBYTE
UNIT_MEGABYTE = 1024 * UNIT_KILOBYTE UNIT_MEGABYTE
UNIT_GIGABYTE = 1024 * UNIT_MEGABYTE UNIT_GIGABYTE
UNIT_TERABYTE = 1024 * UNIT_GIGABYTE UNIT_TERABYTE
UNIT_PETABYTE
) )
func BytesToString(bytes uint64) string { func BytesToString(bytes uint64) string {