init commit
This commit is contained in:
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Autoconf/Automake generated files
|
||||||
|
aclocal.m4
|
||||||
|
.deps
|
||||||
|
autom4te.cache
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
ar-lib
|
||||||
|
compile
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
configure
|
||||||
|
depcomp
|
||||||
|
install-sh
|
||||||
|
missing
|
||||||
|
config.guess
|
||||||
|
config.sub
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
# intellij idea configure
|
||||||
|
.idea
|
||||||
|
/citadm
|
||||||
|
/citd
|
||||||
|
*.out
|
||||||
|
examples/*
|
||||||
|
*.bak
|
||||||
21
.travis.yml
Normal file
21
.travis.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
|
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.4
|
||||||
|
- 1.5
|
||||||
|
|
||||||
|
install:
|
||||||
|
- true
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- go get golang.org/x/tools/cmd/vet
|
||||||
|
- go get github.com/kr/godep
|
||||||
|
|
||||||
|
script:
|
||||||
|
- cd ${TRAVIS_BUILD_DIR}
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure
|
||||||
|
- make
|
||||||
|
- hack/verify-gofmt.sh
|
||||||
10
Godeps/Godeps.json
generated
Normal file
10
Godeps/Godeps.json
generated
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"ImportPath": "github.com/gostor/gotgt",
|
||||||
|
"GoVersion": "go1.4.1",
|
||||||
|
"Deps": [
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/golang/glog",
|
||||||
|
"Rev": "fca8c8854093a154ff1eb580aae10276ad6b1b5f"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
5
Godeps/Readme
generated
Normal file
5
Godeps/Readme
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
This directory tree is generated automatically by godep.
|
||||||
|
|
||||||
|
Please do not edit.
|
||||||
|
|
||||||
|
See https://github.com/tools/godep for more information.
|
||||||
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/pkg
|
||||||
|
/bin
|
||||||
191
Godeps/_workspace/src/github.com/golang/glog/LICENSE
generated
vendored
Normal file
191
Godeps/_workspace/src/github.com/golang/glog/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction, and
|
||||||
|
distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||||
|
owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||||
|
that control, are controlled by, or are under common control with that entity.
|
||||||
|
For the purposes of this definition, "control" means (i) the power, direct or
|
||||||
|
indirect, to cause the direction or management of such entity, whether by
|
||||||
|
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||||
|
permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications, including
|
||||||
|
but not limited to software source code, documentation source, and configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical transformation or
|
||||||
|
translation of a Source form, including but not limited to compiled object code,
|
||||||
|
generated documentation, and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||||
|
available under the License, as indicated by a copyright notice that is included
|
||||||
|
in or attached to the work (an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||||
|
is based on (or derived from) the Work and for which the editorial revisions,
|
||||||
|
annotations, elaborations, or other modifications represent, as a whole, an
|
||||||
|
original work of authorship. For the purposes of this License, Derivative Works
|
||||||
|
shall not include works that remain separable from, or merely link (or bind by
|
||||||
|
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including the original version
|
||||||
|
of the Work and any modifications or additions to that Work or Derivative Works
|
||||||
|
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||||
|
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||||
|
on behalf of the copyright owner. For the purposes of this definition,
|
||||||
|
"submitted" means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems, and
|
||||||
|
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||||
|
the purpose of discussing and improving the Work, but excluding communication
|
||||||
|
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||||
|
owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||||
|
of whom a Contribution has been received by Licensor and subsequently
|
||||||
|
incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License.
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||||
|
Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License.
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable (except as stated in this section) patent license to make, have
|
||||||
|
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||||
|
such license applies only to those patent claims licensable by such Contributor
|
||||||
|
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||||
|
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||||
|
submitted. If You institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||||
|
Contribution incorporated within the Work constitutes direct or contributory
|
||||||
|
patent infringement, then any patent licenses granted to You under this License
|
||||||
|
for that Work shall terminate as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution.
|
||||||
|
|
||||||
|
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||||
|
in any medium, with or without modifications, and in Source or Object form,
|
||||||
|
provided that You meet the following conditions:
|
||||||
|
|
||||||
|
You must give any other recipients of the Work or Derivative Works a copy of
|
||||||
|
this License; and
|
||||||
|
You must cause any modified files to carry prominent notices stating that You
|
||||||
|
changed the files; and
|
||||||
|
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||||
|
all copyright, patent, trademark, and attribution notices from the Source form
|
||||||
|
of the Work, excluding those notices that do not pertain to any part of the
|
||||||
|
Derivative Works; and
|
||||||
|
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||||
|
Derivative Works that You distribute must include a readable copy of the
|
||||||
|
attribution notices contained within such NOTICE file, excluding those notices
|
||||||
|
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||||
|
following places: within a NOTICE text file distributed as part of the
|
||||||
|
Derivative Works; within the Source form or documentation, if provided along
|
||||||
|
with the Derivative Works; or, within a display generated by the Derivative
|
||||||
|
Works, if and wherever such third-party notices normally appear. The contents of
|
||||||
|
the NOTICE file are for informational purposes only and do not modify the
|
||||||
|
License. You may add Your own attribution notices within Derivative Works that
|
||||||
|
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||||
|
provided that such additional attribution notices cannot be construed as
|
||||||
|
modifying the License.
|
||||||
|
You may add Your own copyright statement to Your modifications and may provide
|
||||||
|
additional or different license terms and conditions for use, reproduction, or
|
||||||
|
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||||
|
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||||
|
with the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions.
|
||||||
|
|
||||||
|
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||||
|
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||||
|
conditions of this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||||
|
any separate license agreement you may have executed with Licensor regarding
|
||||||
|
such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks.
|
||||||
|
|
||||||
|
This License does not grant permission to use the trade names, trademarks,
|
||||||
|
service marks, or product names of the Licensor, except as required for
|
||||||
|
reasonable and customary use in describing the origin of the Work and
|
||||||
|
reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||||
|
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||||
|
including, without limitation, any warranties or conditions of TITLE,
|
||||||
|
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||||
|
solely responsible for determining the appropriateness of using or
|
||||||
|
redistributing the Work and assume any risks associated with Your exercise of
|
||||||
|
permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability.
|
||||||
|
|
||||||
|
In no event and under no legal theory, whether in tort (including negligence),
|
||||||
|
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||||
|
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special, incidental,
|
||||||
|
or consequential damages of any character arising as a result of this License or
|
||||||
|
out of the use or inability to use the Work (including but not limited to
|
||||||
|
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||||
|
any and all other commercial damages or losses), even if such Contributor has
|
||||||
|
been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability.
|
||||||
|
|
||||||
|
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||||
|
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||||
|
other liability obligations and/or rights consistent with this License. However,
|
||||||
|
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||||
|
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||||
|
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason of your
|
||||||
|
accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following boilerplate
|
||||||
|
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||||
|
identifying information. (Don't include the brackets!) The text should be
|
||||||
|
enclosed in the appropriate comment syntax for the file format. We also
|
||||||
|
recommend that a file or class name and description of purpose be included on
|
||||||
|
the same "printed page" as the copyright notice for easier identification within
|
||||||
|
third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
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.
|
||||||
44
Godeps/_workspace/src/github.com/golang/glog/README
generated
vendored
Normal file
44
Godeps/_workspace/src/github.com/golang/glog/README
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
glog
|
||||||
|
====
|
||||||
|
|
||||||
|
Leveled execution logs for Go.
|
||||||
|
|
||||||
|
This is an efficient pure Go implementation of leveled logs in the
|
||||||
|
manner of the open source C++ package
|
||||||
|
http://code.google.com/p/google-glog
|
||||||
|
|
||||||
|
By binding methods to booleans it is possible to use the log package
|
||||||
|
without paying the expense of evaluating the arguments to the log.
|
||||||
|
Through the -vmodule flag, the package also provides fine-grained
|
||||||
|
control over logging at the file level.
|
||||||
|
|
||||||
|
The comment from glog.go introduces the ideas:
|
||||||
|
|
||||||
|
Package glog implements logging analogous to the Google-internal
|
||||||
|
C++ INFO/ERROR/V setup. It provides functions Info, Warning,
|
||||||
|
Error, Fatal, plus formatting variants such as Infof. It
|
||||||
|
also provides V-style logging controlled by the -v and
|
||||||
|
-vmodule=file=2 flags.
|
||||||
|
|
||||||
|
Basic examples:
|
||||||
|
|
||||||
|
glog.Info("Prepare to repel boarders")
|
||||||
|
|
||||||
|
glog.Fatalf("Initialization failed: %s", err)
|
||||||
|
|
||||||
|
See the documentation for the V function for an explanation
|
||||||
|
of these examples:
|
||||||
|
|
||||||
|
if glog.V(2) {
|
||||||
|
glog.Info("Starting transaction...")
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(2).Infoln("Processed", nItems, "elements")
|
||||||
|
|
||||||
|
|
||||||
|
The repository contains an open source version of the log package
|
||||||
|
used inside Google. The master copy of the source lives inside
|
||||||
|
Google, not here. The code in this repo is for export only and is not itself
|
||||||
|
under development. Feature requests will be ignored.
|
||||||
|
|
||||||
|
Send bug reports to golang-nuts@googlegroups.com.
|
||||||
1180
Godeps/_workspace/src/github.com/golang/glog/glog.go
generated
vendored
Normal file
1180
Godeps/_workspace/src/github.com/golang/glog/glog.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
124
Godeps/_workspace/src/github.com/golang/glog/glog_file.go
generated
vendored
Normal file
124
Godeps/_workspace/src/github.com/golang/glog/glog_file.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
|
||||||
|
//
|
||||||
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// File I/O for logs.
|
||||||
|
|
||||||
|
package glog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MaxSize is the maximum size of a log file in bytes.
|
||||||
|
var MaxSize uint64 = 1024 * 1024 * 1800
|
||||||
|
|
||||||
|
// logDirs lists the candidate directories for new log files.
|
||||||
|
var logDirs []string
|
||||||
|
|
||||||
|
// If non-empty, overrides the choice of directory in which to write logs.
|
||||||
|
// See createLogDirs for the full list of possible destinations.
|
||||||
|
var logDir = flag.String("log_dir", "", "If non-empty, write log files in this directory")
|
||||||
|
|
||||||
|
func createLogDirs() {
|
||||||
|
if *logDir != "" {
|
||||||
|
logDirs = append(logDirs, *logDir)
|
||||||
|
}
|
||||||
|
logDirs = append(logDirs, os.TempDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
pid = os.Getpid()
|
||||||
|
program = filepath.Base(os.Args[0])
|
||||||
|
host = "unknownhost"
|
||||||
|
userName = "unknownuser"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
h, err := os.Hostname()
|
||||||
|
if err == nil {
|
||||||
|
host = shortHostname(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
current, err := user.Current()
|
||||||
|
if err == nil {
|
||||||
|
userName = current.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize userName since it may contain filepath separators on Windows.
|
||||||
|
userName = strings.Replace(userName, `\`, "_", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// shortHostname returns its argument, truncating at the first period.
|
||||||
|
// For instance, given "www.google.com" it returns "www".
|
||||||
|
func shortHostname(hostname string) string {
|
||||||
|
if i := strings.Index(hostname, "."); i >= 0 {
|
||||||
|
return hostname[:i]
|
||||||
|
}
|
||||||
|
return hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
// logName returns a new log file name containing tag, with start time t, and
|
||||||
|
// the name for the symlink for tag.
|
||||||
|
func logName(tag string, t time.Time) (name, link string) {
|
||||||
|
name = fmt.Sprintf("%s.%s.%s.log.%s.%04d%02d%02d-%02d%02d%02d.%d",
|
||||||
|
program,
|
||||||
|
host,
|
||||||
|
userName,
|
||||||
|
tag,
|
||||||
|
t.Year(),
|
||||||
|
t.Month(),
|
||||||
|
t.Day(),
|
||||||
|
t.Hour(),
|
||||||
|
t.Minute(),
|
||||||
|
t.Second(),
|
||||||
|
pid)
|
||||||
|
return name, program + "." + tag
|
||||||
|
}
|
||||||
|
|
||||||
|
var onceLogDirs sync.Once
|
||||||
|
|
||||||
|
// create creates a new log file and returns the file and its filename, which
|
||||||
|
// contains tag ("INFO", "FATAL", etc.) and t. If the file is created
|
||||||
|
// successfully, create also attempts to update the symlink for that tag, ignoring
|
||||||
|
// errors.
|
||||||
|
func create(tag string, t time.Time) (f *os.File, filename string, err error) {
|
||||||
|
onceLogDirs.Do(createLogDirs)
|
||||||
|
if len(logDirs) == 0 {
|
||||||
|
return nil, "", errors.New("log: no log dirs")
|
||||||
|
}
|
||||||
|
name, link := logName(tag, t)
|
||||||
|
var lastErr error
|
||||||
|
for _, dir := range logDirs {
|
||||||
|
fname := filepath.Join(dir, name)
|
||||||
|
f, err := os.Create(fname)
|
||||||
|
if err == nil {
|
||||||
|
symlink := filepath.Join(dir, link)
|
||||||
|
os.Remove(symlink) // ignore err
|
||||||
|
os.Symlink(name, symlink) // ignore err
|
||||||
|
return f, fname, nil
|
||||||
|
}
|
||||||
|
lastErr = err
|
||||||
|
}
|
||||||
|
return nil, "", fmt.Errorf("log: cannot create log: %v", lastErr)
|
||||||
|
}
|
||||||
415
Godeps/_workspace/src/github.com/golang/glog/glog_test.go
generated
vendored
Normal file
415
Godeps/_workspace/src/github.com/golang/glog/glog_test.go
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
|||||||
|
// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
|
||||||
|
//
|
||||||
|
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package glog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
stdLog "log"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test that shortHostname works as advertised.
|
||||||
|
func TestShortHostname(t *testing.T) {
|
||||||
|
for hostname, expect := range map[string]string{
|
||||||
|
"": "",
|
||||||
|
"host": "host",
|
||||||
|
"host.google.com": "host",
|
||||||
|
} {
|
||||||
|
if got := shortHostname(hostname); expect != got {
|
||||||
|
t.Errorf("shortHostname(%q): expected %q, got %q", hostname, expect, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// flushBuffer wraps a bytes.Buffer to satisfy flushSyncWriter.
|
||||||
|
type flushBuffer struct {
|
||||||
|
bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *flushBuffer) Flush() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *flushBuffer) Sync() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap sets the log writers and returns the old array.
|
||||||
|
func (l *loggingT) swap(writers [numSeverity]flushSyncWriter) (old [numSeverity]flushSyncWriter) {
|
||||||
|
l.mu.Lock()
|
||||||
|
defer l.mu.Unlock()
|
||||||
|
old = l.file
|
||||||
|
for i, w := range writers {
|
||||||
|
logging.file[i] = w
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// newBuffers sets the log writers to all new byte buffers and returns the old array.
|
||||||
|
func (l *loggingT) newBuffers() [numSeverity]flushSyncWriter {
|
||||||
|
return l.swap([numSeverity]flushSyncWriter{new(flushBuffer), new(flushBuffer), new(flushBuffer), new(flushBuffer)})
|
||||||
|
}
|
||||||
|
|
||||||
|
// contents returns the specified log value as a string.
|
||||||
|
func contents(s severity) string {
|
||||||
|
return logging.file[s].(*flushBuffer).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// contains reports whether the string is contained in the log.
|
||||||
|
func contains(s severity, str string, t *testing.T) bool {
|
||||||
|
return strings.Contains(contents(s), str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setFlags configures the logging flags how the test expects them.
|
||||||
|
func setFlags() {
|
||||||
|
logging.toStderr = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that Info works as advertised.
|
||||||
|
func TestInfo(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
Info("test")
|
||||||
|
if !contains(infoLog, "I", t) {
|
||||||
|
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||||
|
}
|
||||||
|
if !contains(infoLog, "test", t) {
|
||||||
|
t.Error("Info failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInfoDepth(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
|
||||||
|
f := func() { InfoDepth(1, "depth-test1") }
|
||||||
|
|
||||||
|
// The next three lines must stay together
|
||||||
|
_, _, wantLine, _ := runtime.Caller(0)
|
||||||
|
InfoDepth(0, "depth-test0")
|
||||||
|
f()
|
||||||
|
|
||||||
|
msgs := strings.Split(strings.TrimSuffix(contents(infoLog), "\n"), "\n")
|
||||||
|
if len(msgs) != 2 {
|
||||||
|
t.Fatalf("Got %d lines, expected 2", len(msgs))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, m := range msgs {
|
||||||
|
if !strings.HasPrefix(m, "I") {
|
||||||
|
t.Errorf("InfoDepth[%d] has wrong character: %q", i, m)
|
||||||
|
}
|
||||||
|
w := fmt.Sprintf("depth-test%d", i)
|
||||||
|
if !strings.Contains(m, w) {
|
||||||
|
t.Errorf("InfoDepth[%d] missing %q: %q", i, w, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pull out the line number (between : and ])
|
||||||
|
msg := m[strings.LastIndex(m, ":")+1:]
|
||||||
|
x := strings.Index(msg, "]")
|
||||||
|
if x < 0 {
|
||||||
|
t.Errorf("InfoDepth[%d]: missing ']': %q", i, m)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
line, err := strconv.Atoi(msg[:x])
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("InfoDepth[%d]: bad line number: %q", i, m)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wantLine++
|
||||||
|
if wantLine != line {
|
||||||
|
t.Errorf("InfoDepth[%d]: got line %d, want %d", i, line, wantLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
CopyStandardLogTo("INFO")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that CopyStandardLogTo panics on bad input.
|
||||||
|
func TestCopyStandardLogToPanic(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if s, ok := recover().(string); !ok || !strings.Contains(s, "LOG") {
|
||||||
|
t.Errorf(`CopyStandardLogTo("LOG") should have panicked: %v`, s)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
CopyStandardLogTo("LOG")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that using the standard log package logs to INFO.
|
||||||
|
func TestStandardLog(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
stdLog.Print("test")
|
||||||
|
if !contains(infoLog, "I", t) {
|
||||||
|
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||||
|
}
|
||||||
|
if !contains(infoLog, "test", t) {
|
||||||
|
t.Error("Info failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the header has the correct format.
|
||||||
|
func TestHeader(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
defer func(previous func() time.Time) { timeNow = previous }(timeNow)
|
||||||
|
timeNow = func() time.Time {
|
||||||
|
return time.Date(2006, 1, 2, 15, 4, 5, .067890e9, time.Local)
|
||||||
|
}
|
||||||
|
pid = 1234
|
||||||
|
Info("test")
|
||||||
|
var line int
|
||||||
|
format := "I0102 15:04:05.067890 1234 glog_test.go:%d] test\n"
|
||||||
|
n, err := fmt.Sscanf(contents(infoLog), format, &line)
|
||||||
|
if n != 1 || err != nil {
|
||||||
|
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, contents(infoLog))
|
||||||
|
}
|
||||||
|
// Scanf treats multiple spaces as equivalent to a single space,
|
||||||
|
// so check for correct space-padding also.
|
||||||
|
want := fmt.Sprintf(format, line)
|
||||||
|
if contents(infoLog) != want {
|
||||||
|
t.Errorf("log format error: got:\n\t%q\nwant:\t%q", contents(infoLog), want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that an Error log goes to Warning and Info.
|
||||||
|
// Even in the Info log, the source character will be E, so the data should
|
||||||
|
// all be identical.
|
||||||
|
func TestError(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
Error("test")
|
||||||
|
if !contains(errorLog, "E", t) {
|
||||||
|
t.Errorf("Error has wrong character: %q", contents(errorLog))
|
||||||
|
}
|
||||||
|
if !contains(errorLog, "test", t) {
|
||||||
|
t.Error("Error failed")
|
||||||
|
}
|
||||||
|
str := contents(errorLog)
|
||||||
|
if !contains(warningLog, str, t) {
|
||||||
|
t.Error("Warning failed")
|
||||||
|
}
|
||||||
|
if !contains(infoLog, str, t) {
|
||||||
|
t.Error("Info failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a Warning log goes to Info.
|
||||||
|
// Even in the Info log, the source character will be W, so the data should
|
||||||
|
// all be identical.
|
||||||
|
func TestWarning(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
Warning("test")
|
||||||
|
if !contains(warningLog, "W", t) {
|
||||||
|
t.Errorf("Warning has wrong character: %q", contents(warningLog))
|
||||||
|
}
|
||||||
|
if !contains(warningLog, "test", t) {
|
||||||
|
t.Error("Warning failed")
|
||||||
|
}
|
||||||
|
str := contents(warningLog)
|
||||||
|
if !contains(infoLog, str, t) {
|
||||||
|
t.Error("Info failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a V log goes to Info.
|
||||||
|
func TestV(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
logging.verbosity.Set("2")
|
||||||
|
defer logging.verbosity.Set("0")
|
||||||
|
V(2).Info("test")
|
||||||
|
if !contains(infoLog, "I", t) {
|
||||||
|
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||||
|
}
|
||||||
|
if !contains(infoLog, "test", t) {
|
||||||
|
t.Error("Info failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a vmodule enables a log in this file.
|
||||||
|
func TestVmoduleOn(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
logging.vmodule.Set("glog_test=2")
|
||||||
|
defer logging.vmodule.Set("")
|
||||||
|
if !V(1) {
|
||||||
|
t.Error("V not enabled for 1")
|
||||||
|
}
|
||||||
|
if !V(2) {
|
||||||
|
t.Error("V not enabled for 2")
|
||||||
|
}
|
||||||
|
if V(3) {
|
||||||
|
t.Error("V enabled for 3")
|
||||||
|
}
|
||||||
|
V(2).Info("test")
|
||||||
|
if !contains(infoLog, "I", t) {
|
||||||
|
t.Errorf("Info has wrong character: %q", contents(infoLog))
|
||||||
|
}
|
||||||
|
if !contains(infoLog, "test", t) {
|
||||||
|
t.Error("Info failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a vmodule of another file does not enable a log in this file.
|
||||||
|
func TestVmoduleOff(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
logging.vmodule.Set("notthisfile=2")
|
||||||
|
defer logging.vmodule.Set("")
|
||||||
|
for i := 1; i <= 3; i++ {
|
||||||
|
if V(Level(i)) {
|
||||||
|
t.Errorf("V enabled for %d", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
V(2).Info("test")
|
||||||
|
if contents(infoLog) != "" {
|
||||||
|
t.Error("V logged incorrectly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vGlobs are patterns that match/don't match this file at V=2.
|
||||||
|
var vGlobs = map[string]bool{
|
||||||
|
// Easy to test the numeric match here.
|
||||||
|
"glog_test=1": false, // If -vmodule sets V to 1, V(2) will fail.
|
||||||
|
"glog_test=2": true,
|
||||||
|
"glog_test=3": true, // If -vmodule sets V to 1, V(3) will succeed.
|
||||||
|
// These all use 2 and check the patterns. All are true.
|
||||||
|
"*=2": true,
|
||||||
|
"?l*=2": true,
|
||||||
|
"????_*=2": true,
|
||||||
|
"??[mno]?_*t=2": true,
|
||||||
|
// These all use 2 and check the patterns. All are false.
|
||||||
|
"*x=2": false,
|
||||||
|
"m*=2": false,
|
||||||
|
"??_*=2": false,
|
||||||
|
"?[abc]?_*t=2": false,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that vmodule globbing works as advertised.
|
||||||
|
func testVmoduleGlob(pat string, match bool, t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
defer logging.vmodule.Set("")
|
||||||
|
logging.vmodule.Set(pat)
|
||||||
|
if V(2) != Verbose(match) {
|
||||||
|
t.Errorf("incorrect match for %q: got %t expected %t", pat, V(2), match)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a vmodule globbing works as advertised.
|
||||||
|
func TestVmoduleGlob(t *testing.T) {
|
||||||
|
for glob, match := range vGlobs {
|
||||||
|
testVmoduleGlob(glob, match, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRollover(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
var err error
|
||||||
|
defer func(previous func(error)) { logExitFunc = previous }(logExitFunc)
|
||||||
|
logExitFunc = func(e error) {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
defer func(previous uint64) { MaxSize = previous }(MaxSize)
|
||||||
|
MaxSize = 512
|
||||||
|
|
||||||
|
Info("x") // Be sure we have a file.
|
||||||
|
info, ok := logging.file[infoLog].(*syncBuffer)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("info wasn't created")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("info has initial error: %v", err)
|
||||||
|
}
|
||||||
|
fname0 := info.file.Name()
|
||||||
|
Info(strings.Repeat("x", int(MaxSize))) // force a rollover
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("info has error after big write: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the next log file gets a file name with a different
|
||||||
|
// time stamp.
|
||||||
|
//
|
||||||
|
// TODO: determine whether we need to support subsecond log
|
||||||
|
// rotation. C++ does not appear to handle this case (nor does it
|
||||||
|
// handle Daylight Savings Time properly).
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
Info("x") // create a new file
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error after rotation: %v", err)
|
||||||
|
}
|
||||||
|
fname1 := info.file.Name()
|
||||||
|
if fname0 == fname1 {
|
||||||
|
t.Errorf("info.f.Name did not change: %v", fname0)
|
||||||
|
}
|
||||||
|
if info.nbytes >= MaxSize {
|
||||||
|
t.Errorf("file size was not reset: %d", info.nbytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogBacktraceAt(t *testing.T) {
|
||||||
|
setFlags()
|
||||||
|
defer logging.swap(logging.newBuffers())
|
||||||
|
// The peculiar style of this code simplifies line counting and maintenance of the
|
||||||
|
// tracing block below.
|
||||||
|
var infoLine string
|
||||||
|
setTraceLocation := func(file string, line int, ok bool, delta int) {
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("could not get file:line")
|
||||||
|
}
|
||||||
|
_, file = filepath.Split(file)
|
||||||
|
infoLine = fmt.Sprintf("%s:%d", file, line+delta)
|
||||||
|
err := logging.traceLocation.Set(infoLine)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("error setting log_backtrace_at: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Start of tracing block. These lines know about each other's relative position.
|
||||||
|
_, file, line, ok := runtime.Caller(0)
|
||||||
|
setTraceLocation(file, line, ok, +2) // Two lines between Caller and Info calls.
|
||||||
|
Info("we want a stack trace here")
|
||||||
|
}
|
||||||
|
numAppearances := strings.Count(contents(infoLog), infoLine)
|
||||||
|
if numAppearances < 2 {
|
||||||
|
// Need 2 appearances, one in the log header and one in the trace:
|
||||||
|
// log_test.go:281: I0511 16:36:06.952398 02238 log_test.go:280] we want a stack trace here
|
||||||
|
// ...
|
||||||
|
// github.com/glog/glog_test.go:280 (0x41ba91)
|
||||||
|
// ...
|
||||||
|
// We could be more precise but that would require knowing the details
|
||||||
|
// of the traceback format, which may not be dependable.
|
||||||
|
t.Fatal("got no trace back; log is ", contents(infoLog))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHeader(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
buf, _, _ := logging.header(infoLog, 0)
|
||||||
|
logging.putBuffer(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
202
LICENSE
Normal file
202
LICENSE
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
13
Makefile.am
Normal file
13
Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export GOPATH:=$(abs_top_srcdir)/Godeps/_workspace:$(GOPATH)
|
||||||
|
|
||||||
|
all-local: build-cli build-daemon
|
||||||
|
clean-local:
|
||||||
|
-rm -f citadm citd
|
||||||
|
install-exec-local:
|
||||||
|
$(INSTALL_PROGRAM) citadm $(bindir)
|
||||||
|
$(INSTALL_PROGRAM) citd $(bindir)
|
||||||
|
|
||||||
|
build-cli:
|
||||||
|
go build citadm.go
|
||||||
|
build-daemon:
|
||||||
|
go build citd.go
|
||||||
67
README.md
67
README.md
@@ -1 +1,66 @@
|
|||||||
# gotgt
|
## gotgt [](https://travis-ci.org/gostor/gotgt)
|
||||||
|
|
||||||
|
Cloud Integrated Target framework, this includes two binaries, one is `citadm` which is command line to config and control, the other is `citd` which is a target daemon.
|
||||||
|
|
||||||
|
```
|
||||||
|
# citadm --help
|
||||||
|
Linux SCSI Target administration utility, version 0.1
|
||||||
|
Usage: ./citadm [OPTIONS]
|
||||||
|
|
||||||
|
Application Options:
|
||||||
|
--lld <driver> --mode target --op new --tid <id> --targetname <name>
|
||||||
|
add a new target with <id> and <name>. <id> must not be zero.
|
||||||
|
--lld <driver> --mode target --op delete [--force] --tid <id>
|
||||||
|
delete the specific target with <id>.
|
||||||
|
With force option, the specific target is deleted
|
||||||
|
even if there is an activity.
|
||||||
|
--lld <driver> --mode target --op show
|
||||||
|
show all the targets.
|
||||||
|
--lld <driver> --mode target --op show --tid <id>
|
||||||
|
show the specific target's parameters.
|
||||||
|
--lld <driver> --mode target --op update --tid <id> --name <param> --value <value>
|
||||||
|
change the target parameters of the target with <id>.
|
||||||
|
--lld <driver> --mode target --op bind --tid <id> --initiator-address <address>
|
||||||
|
--lld <driver> --mode target --op bind --tid <id> --initiator-name <name>
|
||||||
|
enable the target to accept the specific initiators.
|
||||||
|
--lld <driver> --mode target --op unbind --tid <id> --initiator-address <address>
|
||||||
|
--lld <driver> --mode target --op unbind --tid <id> --initiator-name <name>
|
||||||
|
disable the specific permitted initiators.
|
||||||
|
--lld <driver> --mode logicalunit --op new --tid <id> --lun <lun>
|
||||||
|
--backing-store <path> --bstype <type> --bsopts <bs options> --bsoflags <options>
|
||||||
|
add a new logical unit with <lun> to the specific
|
||||||
|
target with <id>. The logical unit is offered
|
||||||
|
to the initiators. <path> must be block device files
|
||||||
|
(including LVM and RAID devices) or regular files.
|
||||||
|
bstype option is optional.
|
||||||
|
bsopts are specific to the bstype.
|
||||||
|
bsoflags supported options are sync and direct
|
||||||
|
(sync:direct for both).
|
||||||
|
--lld <driver> --mode logicalunit --op delete --tid <id> --lun <lun>
|
||||||
|
delete the specific logical unit with <lun> that
|
||||||
|
the target with <id> has.
|
||||||
|
--lld <driver> --mode account --op new --user <name> --password <pass>
|
||||||
|
add a new account with <name> and <pass>.
|
||||||
|
--lld <driver> --mode account --op delete --user <name>
|
||||||
|
delete the specific account having <name>.
|
||||||
|
--lld <driver> --mode account --op bind --tid <id> --user <name> [--outgoing]
|
||||||
|
add the specific account having <name> to
|
||||||
|
the specific target with <id>.
|
||||||
|
<user> could be <IncomingUser> or <OutgoingUser>.
|
||||||
|
If you use --outgoing option, the account will
|
||||||
|
be added as an outgoing account.
|
||||||
|
--lld <driver> --mode account --op unbind --tid <id> --user <name> [--outgoing]
|
||||||
|
delete the specific account having <name> from specific
|
||||||
|
target. The --outgoing option must be added if you
|
||||||
|
delete an outgoing account.
|
||||||
|
--lld <driver> --mode lld --op start
|
||||||
|
Start the specified lld without restarting the tgtd process.
|
||||||
|
--control-port <port> use control port <port>
|
||||||
|
|
||||||
|
Help Options:
|
||||||
|
--help
|
||||||
|
display this help and exit
|
||||||
|
|
||||||
|
Report bugs via <https://github.com/gostor/gotgt/issues>.
|
||||||
|
|
||||||
|
```
|
||||||
|
|||||||
35
autogen.sh
Executable file
35
autogen.sh
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
srcdir=`dirname $0`
|
||||||
|
test -z "$srcdir" && srcidr=.
|
||||||
|
|
||||||
|
cd $srcdir
|
||||||
|
|
||||||
|
die()
|
||||||
|
{
|
||||||
|
echo
|
||||||
|
echo "$1"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
aclocal --version < /dev/null > /dev/null 2>&1 || die "You must have aclocal installed to generate the hyper."
|
||||||
|
autoconf --version < /dev/null > /dev/null 2>&1 || die "You must have autoconf installed to generate the hyper."
|
||||||
|
automake --version < /dev/null > /dev/null 2>&1 || die "You must have automake installed to generate the hyper."
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Generating build-system with:"
|
||||||
|
echo " aclocal: $(aclocal --version | head -1)"
|
||||||
|
echo " autoconf: $(autoconf --version | head -1)"
|
||||||
|
echo " automake: $(automake --version | head -1)"
|
||||||
|
echo
|
||||||
|
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
|
||||||
|
aclocal
|
||||||
|
autoconf
|
||||||
|
automake --add-missing
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "type '$srcdir/configure' and 'make' to compile hyper."
|
||||||
|
echo
|
||||||
200
citadm.go
Normal file
200
citadm.go
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SCSI target command line
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/gostor/gotgt/pkg/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AdminMode int
|
||||||
|
type AdminOperation int
|
||||||
|
|
||||||
|
const (
|
||||||
|
OP_NEW = iota
|
||||||
|
OP_DELETE
|
||||||
|
OP_SHOW
|
||||||
|
OP_BIND
|
||||||
|
OP_UNBIND
|
||||||
|
OP_UPDATE
|
||||||
|
OP_STATS
|
||||||
|
OP_START
|
||||||
|
OP_STOP
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MODE_SYSTEM = iota
|
||||||
|
MODE_TARGET
|
||||||
|
MODE_DEVICE
|
||||||
|
MODE_PORTAL
|
||||||
|
MODE_LLD
|
||||||
|
|
||||||
|
MODE_SESSION
|
||||||
|
MODE_CONNECTION
|
||||||
|
MODE_ACCOUNT
|
||||||
|
)
|
||||||
|
|
||||||
|
type AdminRequest struct {
|
||||||
|
Mode AdminMode
|
||||||
|
Operation AdminOperation
|
||||||
|
LLD string
|
||||||
|
Length uint32
|
||||||
|
TID int32
|
||||||
|
SID uint64
|
||||||
|
Lun uint64
|
||||||
|
Cid uint64
|
||||||
|
host_no uint32
|
||||||
|
device_type uint32
|
||||||
|
ac_dir uint32
|
||||||
|
pack uint32
|
||||||
|
force uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// define options
|
||||||
|
//var req AdminRequest
|
||||||
|
flDebug := flag.Bool("debug", false, "Debug mode")
|
||||||
|
flHelp := flag.Bool("help", false, "Help Message")
|
||||||
|
flVersion := flag.Bool("version", false, "Version message")
|
||||||
|
flLLD := flag.String("lld", "", "Low level device")
|
||||||
|
flOperation := flag.String("op", "", "Operation")
|
||||||
|
flMode := flag.String("mode", "", "")
|
||||||
|
flTID := flag.String("tid", "", "")
|
||||||
|
flSID := flag.String("sid", "", "")
|
||||||
|
flCID := flag.String("cid", "", "")
|
||||||
|
flLUN := flag.String("lun", "", "")
|
||||||
|
flName := flag.String("name", "", "")
|
||||||
|
flValue := flag.String("value", "", "")
|
||||||
|
flBS := flag.String("backing-store", "", "")
|
||||||
|
flTarget := flag.String("target", "", "")
|
||||||
|
flInitiatorName := flag.String("initiator-name", "", "")
|
||||||
|
flInitiatorAddress := flag.String("initiator-address", "", "")
|
||||||
|
flUser := flag.String("user", "", "")
|
||||||
|
flPassword := flag.String("password", "", "")
|
||||||
|
flHost := flag.String("host", "", "")
|
||||||
|
flForce := flag.Bool("force", false, "")
|
||||||
|
flDeviceType := flag.String("devicetype", "", "")
|
||||||
|
|
||||||
|
flag.Usage = func() { usage(0) }
|
||||||
|
flag.Parse()
|
||||||
|
if *flHelp {
|
||||||
|
usage(0)
|
||||||
|
}
|
||||||
|
if *flVersion {
|
||||||
|
showVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = flDebug
|
||||||
|
_ = flLLD
|
||||||
|
_ = flOperation
|
||||||
|
_ = flMode
|
||||||
|
_ = flTID
|
||||||
|
_ = flSID
|
||||||
|
_ = flCID
|
||||||
|
_ = flLUN
|
||||||
|
_ = flName
|
||||||
|
_ = flValue
|
||||||
|
_ = flBS
|
||||||
|
_ = flTarget
|
||||||
|
_ = flInitiatorName
|
||||||
|
_ = flInitiatorAddress
|
||||||
|
_ = flUser
|
||||||
|
_ = flPassword
|
||||||
|
_ = flHost
|
||||||
|
_ = flForce
|
||||||
|
_ = flDeviceType
|
||||||
|
}
|
||||||
|
|
||||||
|
func usage(status int) {
|
||||||
|
if status != 0 {
|
||||||
|
fmt.Fprintf(os.Stderr, "Try `%s --help' for more information.\n", os.Args[0])
|
||||||
|
os.Exit(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
var helpMessage = `Linux SCSI Target administration utility, version %s
|
||||||
|
Usage: %s [OPTIONS]
|
||||||
|
|
||||||
|
Application Options:
|
||||||
|
--lld <driver> --mode target --op new --tid <id> --targetname <name>
|
||||||
|
add a new target with <id> and <name>. <id> must not be zero.
|
||||||
|
--lld <driver> --mode target --op delete [--force] --tid <id>
|
||||||
|
delete the specific target with <id>.
|
||||||
|
With force option, the specific target is deleted
|
||||||
|
even if there is an activity.
|
||||||
|
--lld <driver> --mode target --op show
|
||||||
|
show all the targets.
|
||||||
|
--lld <driver> --mode target --op show --tid <id>
|
||||||
|
show the specific target's parameters.
|
||||||
|
--lld <driver> --mode target --op update --tid <id> --name <param> --value <value>
|
||||||
|
change the target parameters of the target with <id>.
|
||||||
|
--lld <driver> --mode target --op bind --tid <id> --initiator-address <address>
|
||||||
|
--lld <driver> --mode target --op bind --tid <id> --initiator-name <name>
|
||||||
|
enable the target to accept the specific initiators.
|
||||||
|
--lld <driver> --mode target --op unbind --tid <id> --initiator-address <address>
|
||||||
|
--lld <driver> --mode target --op unbind --tid <id> --initiator-name <name>
|
||||||
|
disable the specific permitted initiators.
|
||||||
|
--lld <driver> --mode logicalunit --op new --tid <id> --lun <lun>
|
||||||
|
--backing-store <path> --bstype <type> --bsopts <bs options> --bsoflags <options>
|
||||||
|
add a new logical unit with <lun> to the specific
|
||||||
|
target with <id>. The logical unit is offered
|
||||||
|
to the initiators. <path> must be block device files
|
||||||
|
(including LVM and RAID devices) or regular files.
|
||||||
|
bstype option is optional.
|
||||||
|
bsopts are specific to the bstype.
|
||||||
|
bsoflags supported options are sync and direct
|
||||||
|
(sync:direct for both).
|
||||||
|
--lld <driver> --mode logicalunit --op delete --tid <id> --lun <lun>
|
||||||
|
delete the specific logical unit with <lun> that
|
||||||
|
the target with <id> has.
|
||||||
|
--lld <driver> --mode account --op new --user <name> --password <pass>
|
||||||
|
add a new account with <name> and <pass>.
|
||||||
|
--lld <driver> --mode account --op delete --user <name>
|
||||||
|
delete the specific account having <name>.
|
||||||
|
--lld <driver> --mode account --op bind --tid <id> --user <name> [--outgoing]
|
||||||
|
add the specific account having <name> to
|
||||||
|
the specific target with <id>.
|
||||||
|
<user> could be <IncomingUser> or <OutgoingUser>.
|
||||||
|
If you use --outgoing option, the account will
|
||||||
|
be added as an outgoing account.
|
||||||
|
--lld <driver> --mode account --op unbind --tid <id> --user <name> [--outgoing]
|
||||||
|
delete the specific account having <name> from specific
|
||||||
|
target. The --outgoing option must be added if you
|
||||||
|
delete an outgoing account.
|
||||||
|
--lld <driver> --mode lld --op start
|
||||||
|
Start the specified lld without restarting the tgtd process.
|
||||||
|
--control-port <port> use control port <port>
|
||||||
|
|
||||||
|
Help Options:
|
||||||
|
--help
|
||||||
|
display this help and exit
|
||||||
|
|
||||||
|
Report bugs via <https://github.com/gostor/gotgt/issues>.
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
fmt.Printf(helpMessage, version.VERSION, os.Args[0])
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func showVersion() {
|
||||||
|
fmt.Printf("%s\n", version.VERSION)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
31
citd.go
Normal file
31
citd.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SCSI target daemon
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_, err := net.Listen("tcp", ":3260")
|
||||||
|
if err != nil {
|
||||||
|
glog.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
60
configure.ac
Normal file
60
configure.ac
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# -*- Autoconf -*-
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
AC_PREREQ([2.69])
|
||||||
|
AC_INIT([runv], [0.4.0], [hyper.sh])
|
||||||
|
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||||
|
|
||||||
|
# Checks for programs.
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_AR
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
AC_CANONICAL_BUILD
|
||||||
|
|
||||||
|
case $build_os in
|
||||||
|
darwin*)
|
||||||
|
AM_CONDITIONAL([ON_DARWIN], [ true ])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AM_CONDITIONAL([ON_DARWIN], [ false ])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Checks for go tool chain
|
||||||
|
AC_CHECK_PROG([has_go], [go], [yes], [no])
|
||||||
|
if test "x$has_go" != "xyes" ; then
|
||||||
|
AC_MSG_ERROR(Unable to find go binary in PATH)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Platform specific setup
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
case $host_os in
|
||||||
|
linux*) AM_CONDITIONAL([ON_LINUX], [ true ]) ;;
|
||||||
|
*) AM_CONDITIONAL([ON_LINUX], [ false ]) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Checks for header files.
|
||||||
|
AC_CHECK_HEADERS([stdlib.h string.h])
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_CHECK_HEADER_STDBOOL
|
||||||
|
AC_TYPE_PID_T
|
||||||
|
AC_TYPE_UINT32_T
|
||||||
|
AC_TYPE_UINT8_T
|
||||||
|
|
||||||
|
# Checks for library functions.
|
||||||
|
AC_FUNC_MALLOC
|
||||||
|
AC_CHECK_FUNCS([strdup])
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
AC_MSG_RESULT([
|
||||||
|
${PACKAGE} ${VERSION}
|
||||||
|
build OS: ${build_os}
|
||||||
|
prefix: ${prefix}
|
||||||
|
|
||||||
|
has go: ${has_go}
|
||||||
|
])
|
||||||
21
hack/verify-gofmt.sh
Executable file
21
hack/verify-gofmt.sh
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
find_files() {
|
||||||
|
find . -not \( \
|
||||||
|
\( \
|
||||||
|
-wholename '*/Godeps/*' \
|
||||||
|
\) -prune \
|
||||||
|
\) -name '*.go'
|
||||||
|
}
|
||||||
|
|
||||||
|
GOFMT="gofmt -s"
|
||||||
|
bad_files=$(find_files | xargs $GOFMT -l)
|
||||||
|
if [[ -n "${bad_files}" ]]; then
|
||||||
|
echo "!!! '$GOFMT' needs to be run on the following files: "
|
||||||
|
echo "${bad_files}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
18
pkg/apiserver/api_installer.go
Normal file
18
pkg/apiserver/api_installer.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package apiserver contains the code that provides a rest.ful api service.
|
||||||
|
package apiserver
|
||||||
18
pkg/apiserver/apiserver.go
Normal file
18
pkg/apiserver/apiserver.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package apiserver contains the code that provides a rest.ful api service.
|
||||||
|
package apiserver
|
||||||
18
pkg/apiserver/doc.go
Normal file
18
pkg/apiserver/doc.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package apiserver contains the code that provides a rest.ful api service.
|
||||||
|
package apiserver
|
||||||
17
pkg/apiserver/handlers.go
Normal file
17
pkg/apiserver/handlers.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package apiserver
|
||||||
24
pkg/port/iscsit/auth.go
Normal file
24
pkg/port/iscsit/auth.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iscsit
|
||||||
|
|
||||||
|
type AuthMethod int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AuthNone = iota
|
||||||
|
AuthChap
|
||||||
|
)
|
||||||
84
pkg/port/iscsit/iscsit.go
Normal file
84
pkg/port/iscsit/iscsit.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// iSCSI Target Driver
|
||||||
|
package iscsit
|
||||||
|
|
||||||
|
type ISCSIDiscoveryMethod string
|
||||||
|
|
||||||
|
var (
|
||||||
|
ISCSIDiscoverySendTargets ISCSIDiscoveryMethod = "sendtargets"
|
||||||
|
ISCSIDiscoveryStaticConfig ISCSIDiscoveryMethod = "static"
|
||||||
|
ISCSIDiscoveryISNS ISCSIDiscoveryMethod = "isns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ISCSIRedirectInfo struct {
|
||||||
|
Address string
|
||||||
|
Port int
|
||||||
|
Reason uint8
|
||||||
|
Callback string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ISCSITarget struct {
|
||||||
|
Sessions []*ISCSISession
|
||||||
|
SessionParam []ISCSISessionParam
|
||||||
|
TID int
|
||||||
|
Alias string
|
||||||
|
MaxSessions int
|
||||||
|
RedirectInfo ISCSIRedirectInfo
|
||||||
|
Rdma int
|
||||||
|
NopInterval int
|
||||||
|
NopCount int
|
||||||
|
}
|
||||||
|
|
||||||
|
type ISCSITargetDriver struct {
|
||||||
|
SCSITargetDriver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) Init() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) Exit() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) CreateTarget(target *SCSITarget) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) DestroyTarget(target *SCSITarget) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) CreatePortal(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) DestroyPortal(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) CreateLu(lu *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tgt *ISCSITargetDriver) GetLun(lun uint8) (uint64, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
func (tgt *ISCSITargetDriver) CommandNotify(nid uint64, result int, cmd *SCSICommand) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
85
pkg/port/iscsit/login.go
Normal file
85
pkg/port/iscsit/login.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iscsit
|
||||||
|
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
func (m *Message) loginRespBytes() []byte {
|
||||||
|
// rfc7143 11.13
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
// byte 0
|
||||||
|
buf.WriteByte(byte(OpLoginResp))
|
||||||
|
var b byte
|
||||||
|
if m.Transit {
|
||||||
|
b |= 0x80
|
||||||
|
}
|
||||||
|
if m.Cont {
|
||||||
|
b |= 0x40
|
||||||
|
}
|
||||||
|
b |= byte(m.CSG&0xff) << 2
|
||||||
|
b |= byte(m.NSG & 0xff)
|
||||||
|
// byte 1
|
||||||
|
buf.WriteByte(b)
|
||||||
|
|
||||||
|
b = 0
|
||||||
|
buf.WriteByte(b) // version-max
|
||||||
|
buf.WriteByte(b) // version-active
|
||||||
|
buf.WriteByte(b) // ahsLen
|
||||||
|
buf.Write(MarshalUint64(uint64(len(m.RawData)))[5:]) // data segment length, no padding
|
||||||
|
buf.Write(MarshalUint64(m.ISID)[2:])
|
||||||
|
buf.Write(MarshalUint64(uint64(m.TSIH))[6:])
|
||||||
|
buf.Write(MarshalUint64(uint64(m.TaskTag))[4:])
|
||||||
|
buf.WriteByte(b)
|
||||||
|
buf.WriteByte(b)
|
||||||
|
buf.WriteByte(b)
|
||||||
|
buf.WriteByte(b) // "reserved"
|
||||||
|
buf.Write(MarshalUint64(uint64(m.StatSN))[4:])
|
||||||
|
buf.Write(MarshalUint64(uint64(m.ExpCmdSN))[4:])
|
||||||
|
buf.Write(MarshalUint64(uint64(m.MaxCmdSN))[4:])
|
||||||
|
buf.WriteByte(byte(m.StatusClass))
|
||||||
|
buf.WriteByte(byte(m.StatusDetail))
|
||||||
|
buf.WriteByte(b)
|
||||||
|
buf.WriteByte(b) // "reserved"
|
||||||
|
var bs [8]byte
|
||||||
|
buf.Write(bs[:])
|
||||||
|
rd := m.RawData
|
||||||
|
for len(rd)%4 != 0 {
|
||||||
|
rd = append(rd, 0)
|
||||||
|
}
|
||||||
|
buf.Write(rd)
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stage int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SecurityNegotiation Stage = 0
|
||||||
|
LoginOperationalNegotiation = 1
|
||||||
|
FullFeaturePhase = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s Stage) String() string {
|
||||||
|
switch s {
|
||||||
|
case SecurityNegotiation:
|
||||||
|
return "Security Negotiation"
|
||||||
|
case LoginOperationalNegotiation:
|
||||||
|
return "Login Operational Negotiation"
|
||||||
|
case FullFeaturePhase:
|
||||||
|
return "Full Feature Phase"
|
||||||
|
}
|
||||||
|
return "Unknown Stage"
|
||||||
|
}
|
||||||
41
pkg/port/iscsit/logout.go
Normal file
41
pkg/port/iscsit/logout.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iscsit
|
||||||
|
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
func (m *Message) logoutRespBytes() []byte {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
buf.WriteByte(byte(OpLogoutResp))
|
||||||
|
buf.WriteByte(0x80)
|
||||||
|
buf.WriteByte(0x00) // response
|
||||||
|
buf.WriteByte(0x00)
|
||||||
|
for i := 4; i < 16; i++ {
|
||||||
|
buf.WriteByte(0x00)
|
||||||
|
}
|
||||||
|
buf.Write(MarshalUint64(uint64(m.TaskTag))[4:])
|
||||||
|
for i := 20; i < 24; i++ {
|
||||||
|
buf.WriteByte(0x00)
|
||||||
|
}
|
||||||
|
buf.Write(MarshalUint64(uint64(m.StatSN))[4:])
|
||||||
|
buf.Write(MarshalUint64(uint64(m.ExpCmdSN))[4:])
|
||||||
|
buf.Write(MarshalUint64(uint64(m.MaxCmdSN))[4:])
|
||||||
|
for i := 36; i < 48; i++ {
|
||||||
|
buf.WriteByte(0x00)
|
||||||
|
}
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
276
pkg/port/iscsit/packet.go
Normal file
276
pkg/port/iscsit/packet.go
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package packet implements the iSCSI PDU packet format as specified in
|
||||||
|
// rfc7143 section 11.
|
||||||
|
package iscsit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OpCode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Defined on the initiator.
|
||||||
|
OpNoopOut OpCode = 0x00
|
||||||
|
OpSCSICmd = 0x01
|
||||||
|
OpSCSITaskReq = 0x02
|
||||||
|
OpLoginReq = 0x03
|
||||||
|
OpTextReq = 0x04
|
||||||
|
OpSCSIOut = 0x05
|
||||||
|
OpLogoutReq = 0x06
|
||||||
|
OpSNACKReq = 0x10
|
||||||
|
// Defined on the target.
|
||||||
|
OpNoopIn OpCode = 0x20
|
||||||
|
OpSCSIResp = 0x21
|
||||||
|
OpSCSITaskResp = 0x22
|
||||||
|
OpLoginResp = 0x23
|
||||||
|
OpTextResp = 0x24
|
||||||
|
OpSCSIIn = 0x25
|
||||||
|
OpLogoutResp = 0x26
|
||||||
|
OpReady = 0x31
|
||||||
|
OpAsync = 0x32
|
||||||
|
OpReject = 0x3f
|
||||||
|
)
|
||||||
|
|
||||||
|
var opCodeMap = map[OpCode]string{
|
||||||
|
OpNoopOut: "NOP-Out",
|
||||||
|
OpSCSICmd: "SCSI Command",
|
||||||
|
OpSCSITaskReq: "SCSI Task Management FunctionRequest",
|
||||||
|
OpLoginReq: "Login Request",
|
||||||
|
OpTextReq: "Text Request",
|
||||||
|
OpSCSIOut: "SCSI Data-Out (write)",
|
||||||
|
OpLogoutReq: "Logout Request",
|
||||||
|
OpSNACKReq: "SNACK Request",
|
||||||
|
OpNoopIn: "NOP-In",
|
||||||
|
OpSCSIResp: "SCSI Response",
|
||||||
|
OpSCSITaskResp: "SCSI Task Management Function Response",
|
||||||
|
OpLoginResp: "Login Response",
|
||||||
|
OpTextResp: "Text Response",
|
||||||
|
OpSCSIIn: "SCSI Data-In (read)",
|
||||||
|
OpLogoutResp: "Logout Response",
|
||||||
|
OpReady: "Ready To Transfer (R2T)",
|
||||||
|
OpAsync: "Asynchronous Message",
|
||||||
|
OpReject: "Reject",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c OpCode) String() string {
|
||||||
|
s := opCodeMap[c]
|
||||||
|
if s == "" {
|
||||||
|
s = fmt.Sprintf("Unknown Code: %x", int(c))
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
OpCode OpCode
|
||||||
|
RawHeader []byte
|
||||||
|
DataLen int
|
||||||
|
RawData []byte
|
||||||
|
Final bool
|
||||||
|
Immediate bool
|
||||||
|
TaskTag uint32
|
||||||
|
ExpCmdSN, MaxCmdSN uint32
|
||||||
|
AHSLen int
|
||||||
|
|
||||||
|
ConnID uint16 // Connection ID.
|
||||||
|
CmdSN uint32 // Command serial number.
|
||||||
|
ExpStatSN uint32 // Expected status serial.
|
||||||
|
|
||||||
|
Read, Write bool
|
||||||
|
LUN uint8
|
||||||
|
Transit bool // Transit bit.
|
||||||
|
Cont bool // Continue bit.
|
||||||
|
CSG, NSG Stage // Current Stage, Next Stage.
|
||||||
|
ISID uint64 // Initiator part of the SSID.
|
||||||
|
TSIH uint16 // Target-assigned Session Identifying Handle.
|
||||||
|
StatSN uint32 // Status serial number.
|
||||||
|
|
||||||
|
// For login response.
|
||||||
|
StatusClass uint8
|
||||||
|
StatusDetail uint8
|
||||||
|
|
||||||
|
// SCSI commands
|
||||||
|
ExpectedDataLen uint32
|
||||||
|
CDB []byte
|
||||||
|
Status Status
|
||||||
|
SCSIResponse Response
|
||||||
|
|
||||||
|
// Data-In
|
||||||
|
HasStatus bool
|
||||||
|
DataSN uint32
|
||||||
|
BufferOffset uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) Bytes() []byte {
|
||||||
|
switch m.OpCode {
|
||||||
|
case OpLoginResp:
|
||||||
|
return m.loginRespBytes()
|
||||||
|
case OpLogoutResp:
|
||||||
|
return m.logoutRespBytes()
|
||||||
|
case OpSCSIResp:
|
||||||
|
return m.scsiCmdRespBytes()
|
||||||
|
case OpSCSIIn:
|
||||||
|
return m.dataInBytes()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) String() string {
|
||||||
|
var s []string
|
||||||
|
s = append(s, fmt.Sprintf("Op: %v", m.OpCode))
|
||||||
|
s = append(s, fmt.Sprintf("Final = %v", m.Final))
|
||||||
|
s = append(s, fmt.Sprintf("Immediate = %v", m.Immediate))
|
||||||
|
s = append(s, fmt.Sprintf("Data Segment Length = %d", m.DataLen))
|
||||||
|
s = append(s, fmt.Sprintf("Task Tag = %x", m.TaskTag))
|
||||||
|
s = append(s, fmt.Sprintf("AHS Length = %d", m.AHSLen))
|
||||||
|
switch m.OpCode {
|
||||||
|
case OpLoginReq:
|
||||||
|
s = append(s, fmt.Sprintf("ISID = %x", m.ISID))
|
||||||
|
s = append(s, fmt.Sprintf("Transit = %v", m.Transit))
|
||||||
|
s = append(s, fmt.Sprintf("Continue = %v", m.Cont))
|
||||||
|
s = append(s, fmt.Sprintf("Current Stage = %v", m.CSG))
|
||||||
|
s = append(s, fmt.Sprintf("Next Stage = %v", m.NSG))
|
||||||
|
case OpLoginResp:
|
||||||
|
s = append(s, fmt.Sprintf("ISID = %x", m.ISID))
|
||||||
|
s = append(s, fmt.Sprintf("Transit = %v", m.Transit))
|
||||||
|
s = append(s, fmt.Sprintf("Continue = %v", m.Cont))
|
||||||
|
s = append(s, fmt.Sprintf("Current Stage = %v", m.CSG))
|
||||||
|
s = append(s, fmt.Sprintf("Next Stage = %v", m.NSG))
|
||||||
|
s = append(s, fmt.Sprintf("Status Class = %d", m.StatusClass))
|
||||||
|
s = append(s, fmt.Sprintf("Status Detail = %d", m.StatusDetail))
|
||||||
|
case OpSCSICmd:
|
||||||
|
s = append(s, fmt.Sprintf("LUN = %d", m.LUN))
|
||||||
|
s = append(s, fmt.Sprintf("ExpectedDataLen = %d", m.ExpectedDataLen))
|
||||||
|
s = append(s, fmt.Sprintf("CmdSN = %d", m.CmdSN))
|
||||||
|
s = append(s, fmt.Sprintf("ExpStatSN = %d", m.ExpStatSN))
|
||||||
|
s = append(s, fmt.Sprintf("Read = %v", m.Read))
|
||||||
|
s = append(s, fmt.Sprintf("Write = %v", m.Write))
|
||||||
|
s = append(s, fmt.Sprintf("CDB = %x", m.CDB))
|
||||||
|
case OpSCSIResp:
|
||||||
|
s = append(s, fmt.Sprintf("StatSN = %d", m.StatSN))
|
||||||
|
s = append(s, fmt.Sprintf("ExpCmdSN = %d", m.ExpCmdSN))
|
||||||
|
s = append(s, fmt.Sprintf("MaxCmdSN = %d", m.MaxCmdSN))
|
||||||
|
}
|
||||||
|
return strings.Join(s, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response composes a reply to the given message with the appropriate bits set.
|
||||||
|
func (m *Message) Response(r *Message) {
|
||||||
|
r.TaskTag = m.TaskTag
|
||||||
|
r.ConnID = m.ConnID
|
||||||
|
r.ISID = m.ISID
|
||||||
|
}
|
||||||
|
|
||||||
|
func Next(r io.Reader) (*Message, error) {
|
||||||
|
buf := make([]byte, 48) // TODO: sync.Pool
|
||||||
|
if _, err := io.ReadFull(r, buf); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m, err := parseHeader(buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m.RawHeader = buf
|
||||||
|
if m.DataLen > 0 {
|
||||||
|
dl := m.DataLen
|
||||||
|
for dl%4 > 0 {
|
||||||
|
dl++
|
||||||
|
}
|
||||||
|
data := make([]byte, dl)
|
||||||
|
if _, err := io.ReadFull(r, data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m.RawData = data[:m.DataLen]
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseUint parses the given slice as a network-byte-ordered integer. If
|
||||||
|
// there are more than 8 bytes in data, it overflows.
|
||||||
|
func ParseUint(data []byte) uint64 {
|
||||||
|
var out uint64
|
||||||
|
for i := 0; i < len(data); i++ {
|
||||||
|
out += uint64(data[len(data)-i-1]) << uint(8*i)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalUint64(i uint64) []byte {
|
||||||
|
var data []byte
|
||||||
|
for j := 0; j < 8; j++ {
|
||||||
|
b := byte(i >> uint(8*(7-j)) & 0xff)
|
||||||
|
data = append(data, b)
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHeader(data []byte) (*Message, error) {
|
||||||
|
if len(data) != 48 {
|
||||||
|
return nil, fmt.Errorf("garbled header")
|
||||||
|
}
|
||||||
|
// TODO: sync.Pool
|
||||||
|
m := &Message{}
|
||||||
|
m.Immediate = 0x40&data[0] == 0x40
|
||||||
|
m.OpCode = OpCode(data[0] & 0x3f)
|
||||||
|
m.Final = 0x80&data[1] == 0x80
|
||||||
|
m.AHSLen = int(data[4]) * 4
|
||||||
|
m.DataLen = int(ParseUint(data[5:8]))
|
||||||
|
m.TaskTag = uint32(ParseUint(data[16:20]))
|
||||||
|
switch m.OpCode {
|
||||||
|
case OpSCSICmd:
|
||||||
|
m.LUN = uint8(data[9])
|
||||||
|
m.ExpectedDataLen = uint32(ParseUint(data[20:24]))
|
||||||
|
m.CmdSN = uint32(ParseUint(data[24:28]))
|
||||||
|
m.Read = data[1]&0x40 == 0x40
|
||||||
|
m.Write = data[1]&0x20 == 0x20
|
||||||
|
m.CDB = data[32:48]
|
||||||
|
m.ExpStatSN = uint32(ParseUint(data[28:32]))
|
||||||
|
case OpSCSIResp:
|
||||||
|
case OpLoginReq:
|
||||||
|
m.Transit = m.Final
|
||||||
|
m.Cont = data[1]&0x40 == 0x40
|
||||||
|
if m.Cont && m.Transit {
|
||||||
|
// rfc7143 11.12.2
|
||||||
|
return nil, fmt.Errorf("transit and continue bits set in same login request")
|
||||||
|
}
|
||||||
|
m.CSG = Stage(data[1]&0xc) >> 2
|
||||||
|
m.NSG = Stage(data[1] & 0x3)
|
||||||
|
m.ISID = uint64(ParseUint(data[8:14]))
|
||||||
|
m.TSIH = uint16(ParseUint(data[14:16]))
|
||||||
|
m.ConnID = uint16(ParseUint(data[20:22]))
|
||||||
|
m.CmdSN = uint32(ParseUint(data[24:28]))
|
||||||
|
m.ExpStatSN = uint32(ParseUint(data[28:32]))
|
||||||
|
case OpLoginResp:
|
||||||
|
m.Transit = m.Final
|
||||||
|
m.Cont = data[1]&0x40 == 0x40
|
||||||
|
if m.Cont && m.Transit {
|
||||||
|
// rfc7143 11.12.2
|
||||||
|
return nil, fmt.Errorf("transit and continue bits set in same login request")
|
||||||
|
}
|
||||||
|
m.CSG = Stage(data[1]&0xc) >> 2
|
||||||
|
m.NSG = Stage(data[1] & 0x3)
|
||||||
|
m.StatSN = uint32(ParseUint(data[24:28]))
|
||||||
|
m.ExpCmdSN = uint32(ParseUint(data[28:32]))
|
||||||
|
m.MaxCmdSN = uint32(ParseUint(data[32:36]))
|
||||||
|
m.StatusClass = uint8(data[36])
|
||||||
|
m.StatusDetail = uint8(data[37])
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
25
pkg/port/iscsit/portal.go
Normal file
25
pkg/port/iscsit/portal.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iscsit
|
||||||
|
|
||||||
|
type ISCSIPortal struct {
|
||||||
|
Address string
|
||||||
|
Port int
|
||||||
|
Tpgt int
|
||||||
|
Fd int
|
||||||
|
Af int
|
||||||
|
}
|
||||||
84
pkg/port/iscsit/session.go
Normal file
84
pkg/port/iscsit/session.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iscsit
|
||||||
|
|
||||||
|
import "crypto/rand"
|
||||||
|
|
||||||
|
type ISCSISessionParam struct {
|
||||||
|
State int
|
||||||
|
Value uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// Session is an iSCSI session.
|
||||||
|
type ISCSISession struct {
|
||||||
|
Refcount int
|
||||||
|
Initiator string
|
||||||
|
InitiatorAlias string
|
||||||
|
Target *ISCSITarget
|
||||||
|
Isid uint64
|
||||||
|
Tsih uint16
|
||||||
|
// only one connection per session
|
||||||
|
Connections []*ISCSIConnection
|
||||||
|
Commands []*ISCSICommand
|
||||||
|
PendingCommands []*ISCSICommand
|
||||||
|
ExpectionCommandSN uint32
|
||||||
|
MaxQueueCommand uint32
|
||||||
|
SessionParam []ISCSISessionParam
|
||||||
|
Info string
|
||||||
|
Rdma int
|
||||||
|
}
|
||||||
|
|
||||||
|
type ISCSIPdu struct {
|
||||||
|
Bhs ISCSIHeader
|
||||||
|
AhsSize uint
|
||||||
|
DataSize uint
|
||||||
|
}
|
||||||
|
|
||||||
|
type ISCSIConnection struct {
|
||||||
|
State int
|
||||||
|
RxIostate int
|
||||||
|
TxIostate int
|
||||||
|
Refcount int
|
||||||
|
|
||||||
|
Session *ISCSISession
|
||||||
|
|
||||||
|
TID int
|
||||||
|
CID int
|
||||||
|
Auth AuthMethod
|
||||||
|
StatSN uint32
|
||||||
|
ExpectionStatSN uint32
|
||||||
|
CommandSN uint32
|
||||||
|
ExpectionCommandSN uint32
|
||||||
|
MaxCommandSN uint32
|
||||||
|
Request ISCSIPdu
|
||||||
|
Response ISCSIPdu
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new session.
|
||||||
|
func NewISCSISession() (*ISCSISession, error) {
|
||||||
|
var tsih uint16
|
||||||
|
b := make([]byte, 2)
|
||||||
|
if _, err := rand.Read(b); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tsih += uint16(b[0]) << 8
|
||||||
|
tsih += uint16(b[1])
|
||||||
|
|
||||||
|
return &Session{
|
||||||
|
Tsih: tsih,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
76
pkg/scsi/backingstore.go
Normal file
76
pkg/scsi/backingstore.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type BaseBackingStore struct {
|
||||||
|
Name string
|
||||||
|
DataSize int
|
||||||
|
OflagsSupported int
|
||||||
|
}
|
||||||
|
|
||||||
|
type BackingStore interface {
|
||||||
|
Open(dev *SCSILu, path string, fd *int, size *uint64) error
|
||||||
|
Close(dev *SCSILu) error
|
||||||
|
Init(dev *SCSILu, Opts string) error
|
||||||
|
Exit(dev *SCSILu) error
|
||||||
|
CommandSubmit(cmd *SCSICommand) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type BackingStoreFunc func() (BackingStore, error)
|
||||||
|
|
||||||
|
var registeredPlugins = map[name](BackingStoreFunc){}
|
||||||
|
|
||||||
|
func RegisterBackingStore(name string, f BackingStoreFunc) {
|
||||||
|
registeredPlugins[name] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBackingStore(name string) (BackingStore, error) {
|
||||||
|
if name == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
f, ok := registeredPlugins[name]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("BackingStore %s is not found.", name)
|
||||||
|
}
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeBackingStore struct {
|
||||||
|
BaseBackingStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeBackingStore) Open(dev *SCSILu, path string, fd *int, size *uint64) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeBackingStore) Close(dev *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeBackingStore) Init(dev *SCSILu, Opts string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeBackingStore) Exit(dev *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeBackingStore) CommandSubmit(cmd *SCSICommand) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
55
pkg/scsi/backingstore/common.go
Normal file
55
pkg/scsi/backingstore/common.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package backingstore
|
||||||
|
|
||||||
|
import "github.com/gostor/gotgt/pkg/scsi"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
scsi.RegisterBackingStore("file", new)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileBackingStore struct {
|
||||||
|
BaseBackingStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func new() (scsi.BackingStore, error) {
|
||||||
|
return NullBackingStore{
|
||||||
|
Name: "file",
|
||||||
|
DataSize: 0,
|
||||||
|
OflagsSupported: 0,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *FileBackingStore) Open(dev *SCSILu, path string, fd *int, size *uint64) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *FileBackingStore) Close(dev *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *FileBackingStore) Init(dev *SCSILu, Opts string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *FileBackingStore) Exit(dev *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *FileBackingStore) CommandSubmit(cmd *SCSICommand) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
55
pkg/scsi/backingstore/null.go
Normal file
55
pkg/scsi/backingstore/null.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package backingstore
|
||||||
|
|
||||||
|
import "github.com/gostor/gotgt/pkg/scsi"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
scsi.RegisterBackingStore("null", new)
|
||||||
|
}
|
||||||
|
|
||||||
|
type NullBackingStore struct {
|
||||||
|
BaseBackingStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func new() (scsi.BackingStore, error) {
|
||||||
|
return NullBackingStore{
|
||||||
|
Name: "null",
|
||||||
|
DataSize: 0,
|
||||||
|
OflagsSupported: 0,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *NullBackingStore) Open(dev *SCSILu, path string, fd *int, size *uint64) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *NullBackingStore) Close(dev *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *NullBackingStore) Init(dev *SCSILu, Opts string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *NullBackingStore) Exit(dev *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *NullBackingStore) CommandSubmit(cmd *SCSICommand) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
192
pkg/scsi/cmd.go
Normal file
192
pkg/scsi/cmd.go
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
type SCSICommandType byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
TEST_UNIT_READY SCSICommandType = 0x00
|
||||||
|
REZERO_UNIT SCSICommandType = 0x01
|
||||||
|
REQUEST_SENSE SCSICommandType = 0x03
|
||||||
|
FORMAT_UNIT SCSICommandType = 0x04
|
||||||
|
READ_BLOCK_LIMITS SCSICommandType = 0x05
|
||||||
|
REASSIGN_BLOCKS SCSICommandType = 0x07
|
||||||
|
INITIALIZE_ELEMENT_STATUS SCSICommandType = 0x07
|
||||||
|
READ_6 SCSICommandType = 0x08
|
||||||
|
WRITE_6 SCSICommandType = 0x0a
|
||||||
|
SEEK_6 SCSICommandType = 0x0b
|
||||||
|
READ_REVERSE SCSICommandType = 0x0f
|
||||||
|
WRITE_FILEMARKS SCSICommandType = 0x10
|
||||||
|
SPACE SCSICommandType = 0x11
|
||||||
|
INQUIRY SCSICommandType = 0x12
|
||||||
|
RECOVER_BUFFERED_DATA SCSICommandType = 0x14
|
||||||
|
MODE_SELECT SCSICommandType = 0x15
|
||||||
|
RESERVE SCSICommandType = 0x16
|
||||||
|
RELEASE SCSICommandType = 0x17
|
||||||
|
COPY SCSICommandType = 0x18
|
||||||
|
ERASE SCSICommandType = 0x19
|
||||||
|
MODE_SENSE SCSICommandType = 0x1a
|
||||||
|
START_STOP SCSICommandType = 0x1b
|
||||||
|
RECEIVE_DIAGNOSTIC SCSICommandType = 0x1c
|
||||||
|
SEND_DIAGNOSTIC SCSICommandType = 0x1d
|
||||||
|
ALLOW_MEDIUM_REMOVAL SCSICommandType = 0x1e
|
||||||
|
|
||||||
|
SET_WINDOW SCSICommandType = 0x24
|
||||||
|
READ_CAPACITY SCSICommandType = 0x25
|
||||||
|
READ_10 SCSICommandType = 0x28
|
||||||
|
WRITE_10 SCSICommandType = 0x2a
|
||||||
|
SEEK_10 SCSICommandType = 0x2b
|
||||||
|
POSITION_TO_ELEMENT SCSICommandType = 0x2b
|
||||||
|
WRITE_VERIFY SCSICommandType = 0x2e
|
||||||
|
VERIFY_10 SCSICommandType = 0x2f
|
||||||
|
SEARCH_HIGH SCSICommandType = 0x30
|
||||||
|
SEARCH_EQUAL SCSICommandType = 0x31
|
||||||
|
SEARCH_LOW SCSICommandType = 0x32
|
||||||
|
SET_LIMITS SCSICommandType = 0x33
|
||||||
|
PRE_FETCH_10 SCSICommandType = 0x34
|
||||||
|
READ_POSITION SCSICommandType = 0x34
|
||||||
|
SYNCHRONIZE_CACHE SCSICommandType = 0x35
|
||||||
|
LOCK_UNLOCK_CACHE SCSICommandType = 0x36
|
||||||
|
READ_DEFECT_DATA SCSICommandType = 0x37
|
||||||
|
INITIALIZE_ELEMENT_STATUS_WITH_RANGE SCSICommandType = 0x37
|
||||||
|
MEDIUM_SCAN SCSICommandType = 0x38
|
||||||
|
COMPARE SCSICommandType = 0x39
|
||||||
|
COPY_VERIFY SCSICommandType = 0x3a
|
||||||
|
WRITE_BUFFER SCSICommandType = 0x3b
|
||||||
|
READ_BUFFER SCSICommandType = 0x3c
|
||||||
|
UPDATE_BLOCK SCSICommandType = 0x3d
|
||||||
|
READ_LONG SCSICommandType = 0x3e
|
||||||
|
WRITE_LONG SCSICommandType = 0x3f
|
||||||
|
CHANGE_DEFINITION SCSICommandType = 0x40
|
||||||
|
WRITE_SAME SCSICommandType = 0x41
|
||||||
|
UNMAP SCSICommandType = 0x42
|
||||||
|
READ_TOC SCSICommandType = 0x43
|
||||||
|
GET_CONFIGURATION SCSICommandType = 0x46
|
||||||
|
LOG_SELECT SCSICommandType = 0x4c
|
||||||
|
LOG_SENSE SCSICommandType = 0x4d
|
||||||
|
READ_DISK_INFO SCSICommandType = 0x51
|
||||||
|
READ_TRACK_INFO SCSICommandType = 0x52
|
||||||
|
MODE_SELECT_10 SCSICommandType = 0x55
|
||||||
|
RESERVE_10 SCSICommandType = 0x56
|
||||||
|
RELEASE_10 SCSICommandType = 0x57
|
||||||
|
MODE_SENSE_10 SCSICommandType = 0x5a
|
||||||
|
CLOSE_TRACK SCSICommandType = 0x5b
|
||||||
|
READ_BUFFER_CAP SCSICommandType = 0x5c
|
||||||
|
PERSISTENT_RESERVE_IN SCSICommandType = 0x5e
|
||||||
|
PERSISTENT_RESERVE_OUT SCSICommandType = 0x5f
|
||||||
|
VARLEN_CDB SCSICommandType = 0x7f
|
||||||
|
READ_16 SCSICommandType = 0x88
|
||||||
|
COMPARE_AND_WRITE SCSICommandType = 0x89
|
||||||
|
WRITE_16 SCSICommandType = 0x8a
|
||||||
|
ORWRITE_16 SCSICommandType = 0x8b
|
||||||
|
WRITE_VERIFY_16 SCSICommandType = 0x8e
|
||||||
|
VERIFY_16 SCSICommandType = 0x8f
|
||||||
|
PRE_FETCH_16 SCSICommandType = 0x90
|
||||||
|
SYNCHRONIZE_CACHE_16 SCSICommandType = 0x91
|
||||||
|
WRITE_SAME_16 SCSICommandType = 0x93
|
||||||
|
SERVICE_ACTION_IN SCSICommandType = 0x9e
|
||||||
|
SAI_READ_CAPACITY_16 SCSICommandType = 0x10
|
||||||
|
SAI_GET_LBA_STATUS SCSICommandType = 0x12
|
||||||
|
REPORT_LUNS SCSICommandType = 0xa0
|
||||||
|
MAINT_PROTOCOL_IN SCSICommandType = 0xa3
|
||||||
|
MOVE_MEDIUM SCSICommandType = 0xa5
|
||||||
|
EXCHANGE_MEDIUM SCSICommandType = 0xa6
|
||||||
|
READ_12 SCSICommandType = 0xa8
|
||||||
|
WRITE_12 SCSICommandType = 0xaa
|
||||||
|
GET_PERFORMACE SCSICommandType = 0xac
|
||||||
|
READ_DVD_STRUCTURE SCSICommandType = 0xad
|
||||||
|
WRITE_VERIFY_12 SCSICommandType = 0xae
|
||||||
|
VERIFY_12 SCSICommandType = 0xaf
|
||||||
|
SEARCH_HIGH_12 SCSICommandType = 0xb0
|
||||||
|
SEARCH_EQUAL_12 SCSICommandType = 0xb1
|
||||||
|
SEARCH_LOW_12 SCSICommandType = 0xb2
|
||||||
|
READ_ELEMENT_STATUS SCSICommandType = 0xb8
|
||||||
|
SEND_VOLUME_TAG SCSICommandType = 0xb6
|
||||||
|
SET_STREAMING SCSICommandType = 0xb6
|
||||||
|
SET_CD_SPEED SCSICommandType = 0xbb
|
||||||
|
WRITE_LONG_2 SCSICommandType = 0xea
|
||||||
|
)
|
||||||
|
|
||||||
|
type SCSIPRServiceAction byte
|
||||||
|
type SCSIPRType byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
/* PERSISTENT_RESERVE_IN service action codes */
|
||||||
|
PR_IN_READ_KEYS SCSIPRServiceAction = 0x00
|
||||||
|
PR_IN_READ_RESERVATION SCSIPRServiceAction = 0x01
|
||||||
|
PR_IN_REPORT_CAPABILITIES SCSIPRServiceAction = 0x02
|
||||||
|
PR_IN_READ_FULL_STATUS SCSIPRServiceAction = 0x03
|
||||||
|
|
||||||
|
/* PERSISTENT_RESERVE_OUT service action codes */
|
||||||
|
PR_OUT_REGISTER SCSIPRServiceAction = 0x00
|
||||||
|
PR_OUT_RESERVE SCSIPRServiceAction = 0x01
|
||||||
|
PR_OUT_RELEASE SCSIPRServiceAction = 0x02
|
||||||
|
PR_OUT_CLEAR SCSIPRServiceAction = 0x03
|
||||||
|
PR_OUT_PREEMPT SCSIPRServiceAction = 0x04
|
||||||
|
PR_OUT_PREEMPT_AND_ABORT SCSIPRServiceAction = 0x05
|
||||||
|
PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY SCSIPRServiceAction = 0x06
|
||||||
|
PR_OUT_REGISTER_AND_MOVE SCSIPRServiceAction = 0x07
|
||||||
|
|
||||||
|
/* Persistent Reservation scope */
|
||||||
|
PR_LU_SCOPE byte = 0x00
|
||||||
|
|
||||||
|
/* Persistent Reservation Type Mask format */
|
||||||
|
PR_TYPE_WRITE_EXCLUSIVE SCSIPRType = 0x01
|
||||||
|
PR_TYPE_EXCLUSIVE_ACCESS SCSIPRType = 0x03
|
||||||
|
PR_TYPE_WRITE_EXCLUSIVE_REGONLY SCSIPRType = 0x05
|
||||||
|
PR_TYPE_EXCLUSIVE_ACCESS_REGONLY SCSIPRType = 0x06
|
||||||
|
PR_TYPE_WRITE_EXCLUSIVE_ALLREG SCSIPRType = 0x07
|
||||||
|
PR_TYPE_EXCLUSIVE_ACCESS_ALLREG SCSIPRType = 0x08
|
||||||
|
)
|
||||||
|
|
||||||
|
type SCSIDataDirection int
|
||||||
|
|
||||||
|
const (
|
||||||
|
SCSIDataNone = iota
|
||||||
|
SCSIDataWrite
|
||||||
|
SCSIDataRead
|
||||||
|
SCSIDataBidirection
|
||||||
|
)
|
||||||
|
|
||||||
|
type SCSIDataBuffer struct {
|
||||||
|
Buffer uint64
|
||||||
|
Length uint64
|
||||||
|
TransferLength uint32
|
||||||
|
Resid int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type SCSICommand struct {
|
||||||
|
Target *SCSITarget
|
||||||
|
DeviceID uint64
|
||||||
|
Device *SCSILu
|
||||||
|
State uint64
|
||||||
|
Direction SCSIDataDirection
|
||||||
|
InSDBBuffer *SCSIDataBuffer
|
||||||
|
OutSDBBuffer *SCSIDataBuffer
|
||||||
|
// Command ITN ID
|
||||||
|
CommandITNID uint64
|
||||||
|
Offset uint64
|
||||||
|
TL uint32
|
||||||
|
SCB *[]byte
|
||||||
|
SCBLength int
|
||||||
|
Lun []uint8
|
||||||
|
Attribute int
|
||||||
|
Tag uint64
|
||||||
|
Result int
|
||||||
|
SenseBuffer []byte
|
||||||
|
SenseLength int
|
||||||
|
}
|
||||||
89
pkg/scsi/drivers.go
Normal file
89
pkg/scsi/drivers.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Target Driver Interface
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
var SCSITargetDriverState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// just registered
|
||||||
|
SCSI_DRIVER_REGD = iota
|
||||||
|
// initialized ok
|
||||||
|
SCSI_DRIVER_INIT
|
||||||
|
// failed to initialize
|
||||||
|
SCSI_DRIVER_ERR
|
||||||
|
// exited
|
||||||
|
SCSI_DRIVER_EXIT
|
||||||
|
)
|
||||||
|
|
||||||
|
type SCSITargetDriver struct {
|
||||||
|
Name string
|
||||||
|
State SCSITargetDriverState
|
||||||
|
DefaultBST string
|
||||||
|
Targets []*SCSITarget
|
||||||
|
}
|
||||||
|
|
||||||
|
type SCSITargetDriverOps interface {
|
||||||
|
Init() error
|
||||||
|
Exit() error
|
||||||
|
|
||||||
|
CreateTarget(target *SCSITarget) error
|
||||||
|
DestroyTarget(target *SCSITarget) error
|
||||||
|
CreatePortal(name string) error
|
||||||
|
DestroyPortal(name string) error
|
||||||
|
CreateLu(lu *SCSILu) error
|
||||||
|
|
||||||
|
GetLun(lun uint8) (uint64, error)
|
||||||
|
CommandNotify(nid uint64, result int, cmd *SCSICommand) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var fakeSCSITargetDriver SCSITargetDriver
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) Init() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) Exit() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) CreateTarget(target *SCSITarget) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) DestroyTarget(target *SCSITarget) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) CreatePortal(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) DestroyPortal(name string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) CreateLu(lu *SCSILu) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fake *fakeSCSITargetDriver) GetLun(lun uint8) (uint64, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
func (fake *fakeSCSITargetDriver) CommandNotify(nid uint64, result int, cmd *SCSICommand) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
123
pkg/scsi/error.go
Normal file
123
pkg/scsi/error.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
type SCSIError byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
NO_SENSE SCSIError = 0x00
|
||||||
|
RECOVERED_ERROR SCSIError = 0x01
|
||||||
|
NOT_READY SCSIError = 0x02
|
||||||
|
MEDIUM_ERROR SCSIError = 0x03
|
||||||
|
HARDWARE_ERROR SCSIError = 0x04
|
||||||
|
ILLEGAL_REQUEST SCSIError = 0x05
|
||||||
|
UNIT_ATTENTION SCSIError = 0x06
|
||||||
|
DATA_PROTECT SCSIError = 0x07
|
||||||
|
BLANK_CHECK SCSIError = 0x08
|
||||||
|
COPY_ABORTED SCSIError = 0x0a
|
||||||
|
ABORTED_COMMAND SCSIError = 0x0b
|
||||||
|
VOLUME_OVERFLOW SCSIError = 0x0d
|
||||||
|
MISCOMPARE SCSIError = 0x0e
|
||||||
|
)
|
||||||
|
|
||||||
|
type SCSISubError uint16
|
||||||
|
|
||||||
|
var (
|
||||||
|
/* Key 0: No Sense Errors */
|
||||||
|
NO_ADDITIONAL_SENSE SCSISubError = 0x0000
|
||||||
|
ASC_MARK SCSISubError = 0x0001
|
||||||
|
ASC_EOM SCSISubError = 0x0002
|
||||||
|
ASC_BOM SCSISubError = 0x0004
|
||||||
|
ASC_END_OF_DATA SCSISubError = 0x0005
|
||||||
|
ASC_OP_IN_PROGRESS SCSISubError = 0x0016
|
||||||
|
ASC_DRIVE_REQUIRES_CLEANING SCSISubError = 0x8282
|
||||||
|
|
||||||
|
/* Key 1: Recovered Errors */
|
||||||
|
ASC_WRITE_ERROR SCSISubError = 0x0c00
|
||||||
|
ASC_READ_ERROR SCSISubError = 0x1100
|
||||||
|
ASC_RECOVERED_WITH_RETRYS SCSISubError = 0x1701
|
||||||
|
ASC_MEDIA_LOAD_EJECT_ERROR SCSISubError = 0x5300
|
||||||
|
ASC_FAILURE_PREDICTION SCSISubError = 0x5d00
|
||||||
|
|
||||||
|
/* Key 2: Not ready */
|
||||||
|
ASC_CAUSE_NOT_REPORTABLE SCSISubError = 0x0400
|
||||||
|
ASC_BECOMING_READY SCSISubError = 0x0401
|
||||||
|
ASC_INITIALIZING_REQUIRED SCSISubError = 0x0402
|
||||||
|
ASC_CLEANING_CART_INSTALLED SCSISubError = 0x3003
|
||||||
|
ASC_CLEANING_FAILURE SCSISubError = 0x3007
|
||||||
|
ASC_MEDIUM_NOT_PRESENT SCSISubError = 0x3a00
|
||||||
|
ASC_LOGICAL_UNIT_NOT_CONFIG SCSISubError = 0x3e00
|
||||||
|
|
||||||
|
/* Key 3: Medium Errors */
|
||||||
|
ASC_WRITE_ERROR SCSISubError = 0x0c00
|
||||||
|
ASC_UNRECOVERED_READ SCSISubError = 0x1100
|
||||||
|
ASC_RECORDED_ENTITY_NOT_FOUND SCSISubError = 0x1400
|
||||||
|
ASC_UNKNOWN_FORMAT SCSISubError = 0x3001
|
||||||
|
ASC_IMCOMPATIBLE_FORMAT SCSISubError = 0x3002
|
||||||
|
ASC_MEDIUM_FORMAT_CORRUPT SCSISubError = 0x3100
|
||||||
|
ASC_SEQUENTIAL_POSITION_ERR SCSISubError = 0x3b00
|
||||||
|
ASC_WRITE_APPEND_ERR SCSISubError = 0x5000
|
||||||
|
ASC_CARTRIDGE_FAULT SCSISubError = 0x5200
|
||||||
|
ASC_MEDIA_LOAD_OR_EJECT_FAILED SCSISubError = 0x5300
|
||||||
|
|
||||||
|
/* Key 4: Hardware Failure */
|
||||||
|
ASC_COMPRESSION_CHECK SCSISubError = 0x0c04
|
||||||
|
ASC_DECOMPRESSION_CRC SCSISubError = 0x110d
|
||||||
|
ASC_MECHANICAL_POSITIONING_ERROR SCSISubError = 0x1501
|
||||||
|
ASC_MANUAL_INTERVENTION_REQ SCSISubError = 0x0403
|
||||||
|
ASC_HARDWARE_FAILURE SCSISubError = 0x4000
|
||||||
|
ASC_INTERNAL_TGT_FAILURE SCSISubError = 0x4400
|
||||||
|
ASC_ERASE_FAILURE SCSISubError = 0x5100
|
||||||
|
|
||||||
|
/* Key 5: Illegal Request */
|
||||||
|
ASC_PARAMETER_LIST_LENGTH_ERR SCSISubError = 0x1a00
|
||||||
|
ASC_INVALID_OP_CODE SCSISubError = 0x2000
|
||||||
|
ASC_LBA_OUT_OF_RANGE SCSISubError = 0x2100
|
||||||
|
ASC_INVALID_FIELD_IN_CDB SCSISubError = 0x2400
|
||||||
|
ASC_LUN_NOT_SUPPORTED SCSISubError = 0x2500
|
||||||
|
ASC_INVALID_FIELD_IN_PARMS SCSISubError = 0x2600
|
||||||
|
ASC_INVALID_RELEASE_OF_PERSISTENT_RESERVATION SCSISubError = 0x2604
|
||||||
|
ASC_INCOMPATIBLE_FORMAT SCSISubError = 0x3005
|
||||||
|
ASC_SAVING_PARMS_UNSUP SCSISubError = 0x3900
|
||||||
|
ASC_MEDIUM_DEST_FULL SCSISubError = 0x3b0d
|
||||||
|
ASC_MEDIUM_SRC_EMPTY SCSISubError = 0x3b0e
|
||||||
|
ASC_POSITION_PAST_BOM SCSISubError = 0x3b0c
|
||||||
|
ASC_MEDIUM_REMOVAL_PREVENTED SCSISubError = 0x5302
|
||||||
|
ASC_INSUFFICENT_REGISTRATION_RESOURCES SCSISubError = 0x5504
|
||||||
|
ASC_BAD_MICROCODE_DETECTED SCSISubError = 0x8283
|
||||||
|
|
||||||
|
/* Key 6: Unit Attention */
|
||||||
|
ASC_NOT_READY_TO_TRANSITION SCSISubError = 0x2800
|
||||||
|
ASC_POWERON_RESET SCSISubError = 0x2900
|
||||||
|
ASC_I_T_NEXUS_LOSS_OCCURRED SCSISubError = 0x2907
|
||||||
|
ASC_MODE_PARAMETERS_CHANGED SCSISubError = 0x2a01
|
||||||
|
ASC_RESERVATIONS_PREEMPTED SCSISubError = 0x2a03
|
||||||
|
ASC_RESERVATIONS_RELEASED SCSISubError = 0x2a04
|
||||||
|
ASC_INSUFFICIENT_TIME_FOR_OPERATION SCSISubError = 0x2e00
|
||||||
|
ASC_CMDS_CLEARED_BY_ANOTHER_INI SCSISubError = 0x2f00
|
||||||
|
ASC_MICROCODE_DOWNLOADED SCSISubError = 0x3f01
|
||||||
|
ASC_INQUIRY_DATA_HAS_CHANGED SCSISubError = 0x3f03
|
||||||
|
ASC_REPORTED_LUNS_DATA_HAS_CHANGED SCSISubError = 0x3f0e
|
||||||
|
ASC_FAILURE_PREDICTION_FALSE SCSISubError = 0x5dff
|
||||||
|
|
||||||
|
/* Data Protect */
|
||||||
|
ASC_WRITE_PROTECT SCSISubError = 0x2700
|
||||||
|
ASC_MEDIUM_OVERWRITE_ATTEMPTED SCSISubError = 0x300c
|
||||||
|
|
||||||
|
/* Miscompare */
|
||||||
|
ASC_MISCOMPARE_DURING_VERIFY_OPERATION SCSISubError = 0x1d00
|
||||||
|
)
|
||||||
29
pkg/scsi/lun.go
Normal file
29
pkg/scsi/lun.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
type SCSILu struct {
|
||||||
|
FD int
|
||||||
|
Address uint64
|
||||||
|
Size uint64
|
||||||
|
Lun uint64
|
||||||
|
Path string
|
||||||
|
BsoFlags int
|
||||||
|
BlockShift uint
|
||||||
|
ReserveID uint64
|
||||||
|
Target *SCSITarget
|
||||||
|
}
|
||||||
18
pkg/scsi/sbc.go
Normal file
18
pkg/scsi/sbc.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SCSI block command processing
|
||||||
|
package scsi
|
||||||
60
pkg/scsi/scsi.go
Normal file
60
pkg/scsi/scsi.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultBlockShift int = 9
|
||||||
|
DefaultSenseBufferSize int = 252
|
||||||
|
)
|
||||||
|
|
||||||
|
type SAMStat byte
|
||||||
|
type SCSIDeviceType byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
SAM_STAT_GOOD SAMStat = 0x00
|
||||||
|
SAM_STAT_CHECK_CONDITION SAMStat = 0x02
|
||||||
|
SAM_STAT_CONDITION_MET SAMStat = 0x04
|
||||||
|
SAM_STAT_BUSY SAMStat = 0x08
|
||||||
|
SAM_STAT_INTERMEDIATE SAMStat = 0x10
|
||||||
|
SAM_STAT_INTERMEDIATE_CONDITION_MET SAMStat = 0x14
|
||||||
|
SAM_STAT_RESERVATION_CONFLICT SAMStat = 0x18
|
||||||
|
SAM_STAT_COMMAND_TERMINATED SAMStat = 0x22
|
||||||
|
SAM_STAT_TASK_SET_FULL SAMStat = 0x28
|
||||||
|
SAM_STAT_ACA_ACTIVE SAMStat = 0x30
|
||||||
|
SAM_STAT_TASK_ABORTED SAMStat = 0x40
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
TYPE_DISK SCSIDeviceType = 0x00
|
||||||
|
TYPE_TAPE SCSIDeviceType = 0x01
|
||||||
|
TYPE_PRINTER SCSIDeviceType = 0x02
|
||||||
|
TYPE_PROCESSOR SCSIDeviceType = 0x03
|
||||||
|
TYPE_WORM SCSIDeviceType = 0x04
|
||||||
|
TYPE_MMC SCSIDeviceType = 0x05
|
||||||
|
TYPE_SCANNER SCSIDeviceType = 0x06
|
||||||
|
TYPE_MOD SCSIDeviceType = 0x07
|
||||||
|
|
||||||
|
TYPE_MEDIUM_CHANGER SCSIDeviceType = 0x08
|
||||||
|
TYPE_COMM SCSIDeviceType = 0x09
|
||||||
|
TYPE_RAID SCSIDeviceType = 0x0c
|
||||||
|
TYPE_ENCLOSURE SCSIDeviceType = 0x0d
|
||||||
|
TYPE_RBC SCSIDeviceType = 0x0e
|
||||||
|
TYPE_OSD SCSIDeviceType = 0x11
|
||||||
|
TYPE_NO_LUN SCSIDeviceType = 0x7f
|
||||||
|
|
||||||
|
TYPE_PT SCSIDeviceType = 0xff
|
||||||
|
)
|
||||||
103
pkg/scsi/spc.go
Normal file
103
pkg/scsi/spc.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SCSI primary command processing
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protocol Identifier Values
|
||||||
|
*
|
||||||
|
* 0 Fibre Channel (FCP-2)
|
||||||
|
* 1 Parallel SCSI (SPI-5)
|
||||||
|
* 2 SSA (SSA-S3P)
|
||||||
|
* 3 IEEE 1394 (SBP-3)
|
||||||
|
* 4 SCSI Remote Direct Memory Access (SRP)
|
||||||
|
* 5 iSCSI
|
||||||
|
* 6 SAS Serial SCSI Protocol (SAS)
|
||||||
|
* 7 Automation/Drive Interface (ADT)
|
||||||
|
* 8 AT Attachment Interface (ATA/ATAPI-7)
|
||||||
|
*/
|
||||||
|
type ProtocolIdentifier int
|
||||||
|
|
||||||
|
var (
|
||||||
|
PIV_FCP ProtocolIdentifier = iota
|
||||||
|
PIV_SPI ProtocolIdentifier
|
||||||
|
PIV_S3P ProtocolIdentifier
|
||||||
|
PIV_SBP ProtocolIdentifier
|
||||||
|
PIV_SRP ProtocolIdentifier
|
||||||
|
PIV_ISCSI ProtocolIdentifier
|
||||||
|
PIV_SAS ProtocolIdentifier
|
||||||
|
PIV_ADT ProtocolIdentifier
|
||||||
|
PIV_ATA ProtocolIdentifier
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Code Set
|
||||||
|
*
|
||||||
|
* 1 - Designator fild contains binary values
|
||||||
|
* 2 - Designator field contains ASCII printable chars
|
||||||
|
* 3 - Designaotor field contains UTF-8
|
||||||
|
*/
|
||||||
|
type CodeSet int
|
||||||
|
|
||||||
|
var (
|
||||||
|
INQ_CODE_BIN CodeSet = 1
|
||||||
|
INQ_CODE_ASCII CodeSet = 2
|
||||||
|
INQ_CODE_UTF8 CodeSet = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Association field
|
||||||
|
*
|
||||||
|
* 00b - Associated with Logical Unit
|
||||||
|
* 01b - Associated with target port
|
||||||
|
* 10b - Associated with SCSI Target device
|
||||||
|
* 11b - Reserved
|
||||||
|
*/
|
||||||
|
type AssociationField int
|
||||||
|
|
||||||
|
var (
|
||||||
|
ASS_LU AssociationField = 0
|
||||||
|
ASS_TGT_PORT AssociationField = 0x10
|
||||||
|
ASS_TGT_DEV AssociationField = 0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Designator type - SPC-4 Reference
|
||||||
|
*
|
||||||
|
* 0 - Vendor specific - 7.6.3.3
|
||||||
|
* 1 - T10 vendor ID - 7.6.3.4
|
||||||
|
* 2 - EUI-64 - 7.6.3.5
|
||||||
|
* 3 - NAA - 7.6.3.6
|
||||||
|
* 4 - Relative Target port identifier - 7.6.3.7
|
||||||
|
* 5 - Target Port group - 7.6.3.8
|
||||||
|
* 6 - Logical Unit group - 7.6.3.9
|
||||||
|
* 7 - MD5 logical unit identifier - 7.6.3.10
|
||||||
|
* 8 - SCSI name string - 7.6.3.11
|
||||||
|
*/
|
||||||
|
type DesignatorType int
|
||||||
|
|
||||||
|
var (
|
||||||
|
DESG_VENDOR DesignatorType = iota
|
||||||
|
DESG_T10 DesignatorType
|
||||||
|
DESG_EUI64 DesignatorType
|
||||||
|
DESG_NAA DesignatorType
|
||||||
|
DESG_REL_TGT_PORT DesignatorType
|
||||||
|
DESG_TGT_PORT_GRP DesignatorType
|
||||||
|
DESG_LU_GRP DesignatorType
|
||||||
|
DESG_MD5 DesignatorType
|
||||||
|
DESG_SCSI DesignatorType
|
||||||
|
)
|
||||||
31
pkg/scsi/target.go
Normal file
31
pkg/scsi/target.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package scsi
|
||||||
|
|
||||||
|
var SCSITargetState int
|
||||||
|
|
||||||
|
var (
|
||||||
|
TargetOnline SCSITargetState = 1
|
||||||
|
TargetReady SCSITargetState = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type SCSITarget struct {
|
||||||
|
Name string
|
||||||
|
TID int
|
||||||
|
LID int
|
||||||
|
State SCSITargetState
|
||||||
|
}
|
||||||
50
pkg/util/util.go
Normal file
50
pkg/util/util.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package util
|
||||||
|
|
||||||
|
// ParseKVText parses iSCSI key value data.
|
||||||
|
func ParseKVText(txt []byte) map[string]string {
|
||||||
|
m := make(map[string]string)
|
||||||
|
var kv, sep int
|
||||||
|
var key string
|
||||||
|
for i := 0; i < len(txt); i++ {
|
||||||
|
if txt[i] == '=' {
|
||||||
|
if key == "" {
|
||||||
|
sep = i
|
||||||
|
key = string(txt[kv:sep])
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if txt[i] == 0 && key != "" {
|
||||||
|
m[key] = string(txt[sep+1 : i])
|
||||||
|
key = ""
|
||||||
|
kv = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalKVText(kv map[string]string) []byte {
|
||||||
|
var data []byte
|
||||||
|
for k, v := range kv {
|
||||||
|
data = append(data, []byte(k)...)
|
||||||
|
data = append(data, '=')
|
||||||
|
data = append(data, []byte(v)...)
|
||||||
|
data = append(data, 0)
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
21
pkg/version/version.go
Normal file
21
pkg/version/version.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 The GoStor Authors All rights reserved.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package version
|
||||||
|
|
||||||
|
const (
|
||||||
|
VERSION = "0.1"
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user