mirror of
https://github.com/pgsty/minio.git
synced 2026-11-02 05:42:06 +03:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5afd856355 | |||
| 000e360196 | |||
| e6ec645035 | |||
| 483fe4bed5 | |||
| 71c4ff9d10 | |||
| ac58283001 | |||
| 9c8b7306f5 | |||
| 1cf381f1b0 | |||
| ffa6b45d00 | |||
| 4eb788df79 | |||
| f9e8ac429e | |||
| 64288d6eb5 | |||
| 41496e1406 | |||
| e6ebcc4cb6 | |||
| 9cab0f25e0 | |||
| 5c21e89559 |
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
Start by forking the Minio GitHub repository, make changes in a branch and then send a pull request. We encourage pull requests to discuss code changes. Here are the steps in details:
|
||||
|
||||
### Setup your Minio Github Repository
|
||||
### Setup your Minio GitHub Repository
|
||||
Fork [Minio upstream](https://github.com/minio/minio/fork) source repository to your own personal repository. Copy the URL of your Minio fork (you will need it for the `git clone` command below).
|
||||
|
||||
```sh
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# For maintainers only
|
||||
|
||||
### Setup your minio Github Repository
|
||||
### Setup your minio GitHub Repository
|
||||
|
||||
Fork [minio upstream](https://github.com/minio/minio/fork) source repository to your own personal repository.
|
||||
```bash
|
||||
|
||||
@@ -89,7 +89,7 @@ export class BrowserDropdown extends React.Component {
|
||||
<Dropdown.Menu className="dropdown-menu-right">
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/minio/minio">
|
||||
Github <i className="fa fa-github" />
|
||||
GitHub <i className="fa fa-github" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -25,23 +25,16 @@ export class StorageInfo extends React.Component {
|
||||
fetchStorageInfo()
|
||||
}
|
||||
render() {
|
||||
const { total, free } = this.props.storageInfo
|
||||
const used = total - free
|
||||
const usedPercent = used / total * 100 + "%"
|
||||
const freePercent = free * 100 / total
|
||||
const { used } = this.props.storageInfo
|
||||
return (
|
||||
<div className="feh-usage">
|
||||
<div className="feh-used">
|
||||
<div className="fehu-chart">
|
||||
<div style={{ width: usedPercent }} />
|
||||
<div style={{ width: 0 }} />
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<span>Used: </span>
|
||||
{humanize.filesize(total - free)}
|
||||
</li>
|
||||
<li className="pull-right">
|
||||
<span>Free: </span>
|
||||
{humanize.filesize(total - used)}
|
||||
{humanize.filesize(used)}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@ describe("StorageInfo", () => {
|
||||
it("should render without crashing", () => {
|
||||
shallow(
|
||||
<StorageInfo
|
||||
storageInfo={{ total: 100, free: 60 }}
|
||||
storageInfo={{ used: 60 }}
|
||||
fetchStorageInfo={jest.fn()}
|
||||
/>
|
||||
)
|
||||
@@ -32,7 +32,7 @@ describe("StorageInfo", () => {
|
||||
const fetchStorageInfo = jest.fn()
|
||||
shallow(
|
||||
<StorageInfo
|
||||
storageInfo={{ total: 100, free: 60 }}
|
||||
storageInfo={{ used: 60 }}
|
||||
fetchStorageInfo={fetchStorageInfo}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ import * as actionsCommon from "../actions"
|
||||
|
||||
jest.mock("../../web", () => ({
|
||||
StorageInfo: jest.fn(() => {
|
||||
return Promise.resolve({ storageInfo: { Total: 100, Free: 60 } })
|
||||
return Promise.resolve({ storageInfo: { Used: 60 } })
|
||||
}),
|
||||
ServerInfo: jest.fn(() => {
|
||||
return Promise.resolve({
|
||||
@@ -40,7 +40,7 @@ describe("Common actions", () => {
|
||||
it("creates common/SET_STORAGE_INFO after fetching the storage details ", () => {
|
||||
const store = mockStore()
|
||||
const expectedActions = [
|
||||
{ type: "common/SET_STORAGE_INFO", storageInfo: { total: 100, free: 60 } }
|
||||
{ type: "common/SET_STORAGE_INFO", storageInfo: { used: 60 } }
|
||||
]
|
||||
return store.dispatch(actionsCommon.fetchStorageInfo()).then(() => {
|
||||
const actions = store.getActions()
|
||||
|
||||
@@ -34,7 +34,7 @@ export const fetchStorageInfo = () => {
|
||||
return web.StorageInfo().then(res => {
|
||||
const storageInfo = {
|
||||
total: res.storageInfo.Total,
|
||||
free: res.storageInfo.Free
|
||||
used: res.storageInfo.Used
|
||||
}
|
||||
dispatch(setStorageInfo(storageInfo))
|
||||
})
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Disk usage
|
||||
Disk used
|
||||
----------------------------*/
|
||||
.feh-usage {
|
||||
.feh-used {
|
||||
margin-top: 12px;
|
||||
max-width: 285px;
|
||||
|
||||
|
||||
+24
-24
File diff suppressed because one or more lines are too long
@@ -929,9 +929,6 @@ func TestAdminServerInfo(t *testing.T) {
|
||||
if serverInfo.Error != "" {
|
||||
t.Errorf("Unexpected error = %v\n", serverInfo.Error)
|
||||
}
|
||||
if serverInfo.Data.StorageInfo.Free == 0 {
|
||||
t.Error("Expected StorageInfo.Free to be non empty")
|
||||
}
|
||||
if serverInfo.Data.Properties.Region != globalMinioDefaultRegion {
|
||||
t.Errorf("Expected %s, got %s", globalMinioDefaultRegion, serverInfo.Data.Properties.Region)
|
||||
}
|
||||
|
||||
+34
-47
@@ -28,6 +28,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/hash"
|
||||
"github.com/minio/minio/pkg/policy"
|
||||
)
|
||||
|
||||
@@ -209,59 +210,45 @@ func reqSignatureV4Verify(r *http.Request, region string) (s3Error APIErrorCode)
|
||||
|
||||
// Verify if request has valid AWS Signature Version '4'.
|
||||
func isReqAuthenticated(r *http.Request, region string) (s3Error APIErrorCode) {
|
||||
if r == nil {
|
||||
return ErrInternalError
|
||||
}
|
||||
|
||||
if errCode := reqSignatureV4Verify(r, region); errCode != ErrNone {
|
||||
return errCode
|
||||
}
|
||||
|
||||
payload, err := ioutil.ReadAll(r.Body)
|
||||
var (
|
||||
err error
|
||||
contentMD5, contentSHA256 []byte
|
||||
)
|
||||
// Extract 'Content-Md5' if present.
|
||||
if _, ok := r.Header["Content-Md5"]; ok {
|
||||
contentMD5, err = base64.StdEncoding.Strict().DecodeString(r.Header.Get("Content-Md5"))
|
||||
if err != nil || len(contentMD5) == 0 {
|
||||
return ErrInvalidDigest
|
||||
}
|
||||
}
|
||||
|
||||
// Extract either 'X-Amz-Content-Sha256' header or 'X-Amz-Content-Sha256' query parameter (if V4 presigned)
|
||||
// Do not verify 'X-Amz-Content-Sha256' if skipSHA256.
|
||||
if skipSHA256 := skipContentSha256Cksum(r); !skipSHA256 && isRequestPresignedSignatureV4(r) {
|
||||
if sha256Sum, ok := r.URL.Query()["X-Amz-Content-Sha256"]; ok && len(sha256Sum) > 0 {
|
||||
contentSHA256, err = hex.DecodeString(sha256Sum[0])
|
||||
if err != nil {
|
||||
return ErrContentSHA256Mismatch
|
||||
}
|
||||
}
|
||||
} else if _, ok := r.Header["X-Amz-Content-Sha256"]; !skipSHA256 && ok {
|
||||
contentSHA256, err = hex.DecodeString(r.Header.Get("X-Amz-Content-Sha256"))
|
||||
if err != nil || len(contentSHA256) == 0 {
|
||||
return ErrContentSHA256Mismatch
|
||||
}
|
||||
}
|
||||
|
||||
// Verify 'Content-Md5' and/or 'X-Amz-Content-Sha256' if present.
|
||||
// The verification happens implicit during reading.
|
||||
reader, err := hash.NewReader(r.Body, -1, hex.EncodeToString(contentMD5), hex.EncodeToString(contentSHA256))
|
||||
if err != nil {
|
||||
logger.LogIf(context.Background(), err)
|
||||
return ErrInternalError
|
||||
}
|
||||
|
||||
// Populate back the payload.
|
||||
r.Body = ioutil.NopCloser(bytes.NewReader(payload))
|
||||
|
||||
// Verify Content-Md5, if payload is set.
|
||||
if clntMD5B64, ok := r.Header["Content-Md5"]; ok {
|
||||
if clntMD5B64[0] == "" {
|
||||
return ErrInvalidDigest
|
||||
}
|
||||
md5Sum, err := base64.StdEncoding.Strict().DecodeString(clntMD5B64[0])
|
||||
if err != nil {
|
||||
return ErrInvalidDigest
|
||||
}
|
||||
if !bytes.Equal(md5Sum, getMD5Sum(payload)) {
|
||||
return ErrBadDigest
|
||||
}
|
||||
}
|
||||
|
||||
if skipContentSha256Cksum(r) {
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
// Verify that X-Amz-Content-Sha256 Header == sha256(payload)
|
||||
// If X-Amz-Content-Sha256 header is not sent then we don't calculate/verify sha256(payload)
|
||||
sumHex, ok := r.Header["X-Amz-Content-Sha256"]
|
||||
if isRequestPresignedSignatureV4(r) {
|
||||
sumHex, ok = r.URL.Query()["X-Amz-Content-Sha256"]
|
||||
}
|
||||
if ok {
|
||||
if sumHex[0] == "" {
|
||||
return ErrContentSHA256Mismatch
|
||||
}
|
||||
sum, err := hex.DecodeString(sumHex[0])
|
||||
if err != nil {
|
||||
return ErrContentSHA256Mismatch
|
||||
}
|
||||
if !bytes.Equal(sum, getSHA256Sum(payload)) {
|
||||
return ErrContentSHA256Mismatch
|
||||
}
|
||||
return toAPIErrorCode(err)
|
||||
}
|
||||
r.Body = ioutil.NopCloser(reader)
|
||||
return ErrNone
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package cmd
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -361,8 +362,6 @@ func TestIsReqAuthenticated(t *testing.T) {
|
||||
req *http.Request
|
||||
s3Error APIErrorCode
|
||||
}{
|
||||
// When request is nil, internal error is returned.
|
||||
{nil, ErrInternalError},
|
||||
// When request is unsigned, access denied is returned.
|
||||
{mustNewRequest("GET", "http://127.0.0.1:9000", 0, nil, t), ErrAccessDenied},
|
||||
// Empty Content-Md5 header.
|
||||
@@ -376,9 +375,11 @@ func TestIsReqAuthenticated(t *testing.T) {
|
||||
}
|
||||
|
||||
// Validates all testcases.
|
||||
for _, testCase := range testCases {
|
||||
for i, testCase := range testCases {
|
||||
if s3Error := isReqAuthenticated(testCase.req, globalServerConfig.GetRegion()); s3Error != testCase.s3Error {
|
||||
t.Fatalf("Unexpected s3error returned wanted %d, got %d", testCase.s3Error, s3Error)
|
||||
if _, err := ioutil.ReadAll(testCase.req.Body); toAPIErrorCode(err) != testCase.s3Error {
|
||||
t.Fatalf("Test %d: Unexpected S3 error: want %d - got %d (got after reading request %d)", i, testCase.s3Error, s3Error, toAPIErrorCode(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -777,7 +777,7 @@ func (c cacheObjects) StorageInfo(ctx context.Context) (storageInfo StorageInfo)
|
||||
if cfs == nil {
|
||||
continue
|
||||
}
|
||||
info, err := getDiskInfo((cfs.fsPath))
|
||||
info, err := getDiskInfo(cfs.fsPath)
|
||||
logger.GetReqInfo(ctx).AppendTags("cachePath", cfs.fsPath)
|
||||
logger.LogIf(ctx, err)
|
||||
total += info.Total
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2018 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
usageCheckInterval = 12 * time.Hour // 12 hours
|
||||
)
|
||||
|
||||
// getDiskUsage walks the file tree rooted at root, calling usageFn
|
||||
// for each file or directory in the tree, including root.
|
||||
func getDiskUsage(ctx context.Context, root string, usageFn usageFunc) error {
|
||||
return walk(ctx, root+slashSeparator, usageFn)
|
||||
}
|
||||
|
||||
type usageFunc func(ctx context.Context, entry string) error
|
||||
|
||||
// walk recursively descends path, calling walkFn.
|
||||
func walk(ctx context.Context, path string, usageFn usageFunc) error {
|
||||
if err := usageFn(ctx, path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !hasSuffix(path, slashSeparator) {
|
||||
return nil
|
||||
}
|
||||
|
||||
entries, err := readDir(path)
|
||||
if err != nil {
|
||||
return usageFn(ctx, path)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
fname := pathJoin(path, entry)
|
||||
if err = walk(ctx, fname, usageFn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func TestNewMultipartUploadFaultyDisk(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test with disk removed.
|
||||
fs.fsPath = filepath.Join(globalTestTmpDir, "minio-"+nextSuffix())
|
||||
os.RemoveAll(disk)
|
||||
if _, err := fs.NewMultipartUpload(context.Background(), bucketName, objectName, map[string]string{"X-Amz-Meta-xid": "3f"}); err != nil {
|
||||
if !isSameType(err, BucketNotFound{}) {
|
||||
t.Fatal("Unexpected error ", err)
|
||||
|
||||
+64
-9
@@ -26,6 +26,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
@@ -63,6 +64,10 @@ type FSObjects struct {
|
||||
|
||||
// To manage the appendRoutine go-routines
|
||||
nsMutex *nsLockMap
|
||||
|
||||
// Disk usage metrics
|
||||
totalUsed uint64
|
||||
usageCheckInterval time.Duration
|
||||
}
|
||||
|
||||
// Represents the background append file.
|
||||
@@ -102,7 +107,7 @@ func NewFSObjectLayer(fsPath string) (ObjectLayer, error) {
|
||||
}
|
||||
|
||||
var err error
|
||||
if fsPath, err = checkPathValid(fsPath); err != nil {
|
||||
if fsPath, err = getValidPath(fsPath); err != nil {
|
||||
return nil, uiErrUnableToWriteInBackend(err)
|
||||
}
|
||||
|
||||
@@ -129,9 +134,10 @@ func NewFSObjectLayer(fsPath string) (ObjectLayer, error) {
|
||||
rwPool: &fsIOPool{
|
||||
readersMap: make(map[string]*lock.RLockedFile),
|
||||
},
|
||||
nsMutex: newNSLock(false),
|
||||
listPool: newTreeWalkPool(globalLookupTimeout),
|
||||
appendFileMap: make(map[string]*fsAppendFile),
|
||||
nsMutex: newNSLock(false),
|
||||
listPool: newTreeWalkPool(globalLookupTimeout),
|
||||
appendFileMap: make(map[string]*fsAppendFile),
|
||||
usageCheckInterval: usageCheckInterval,
|
||||
}
|
||||
|
||||
// Once the filesystem has initialized hold the read lock for
|
||||
@@ -150,6 +156,7 @@ func NewFSObjectLayer(fsPath string) (ObjectLayer, error) {
|
||||
return nil, uiErrUnableToReadFromBackend(err).Msg("Unable to initialize policy system")
|
||||
}
|
||||
|
||||
go fs.diskUsage(globalServiceDoneCh)
|
||||
go fs.cleanupStaleMultipartUploads(ctx, globalMultipartCleanupInterval, globalMultipartExpiry, globalServiceDoneCh)
|
||||
|
||||
// Return successfully initialized object layer.
|
||||
@@ -164,14 +171,62 @@ func (fs *FSObjects) Shutdown(ctx context.Context) error {
|
||||
return fsRemoveAll(ctx, pathJoin(fs.fsPath, minioMetaTmpBucket, fs.fsUUID))
|
||||
}
|
||||
|
||||
// diskUsage returns du information for the posix path, in a continuous routine.
|
||||
func (fs *FSObjects) diskUsage(doneCh chan struct{}) {
|
||||
ticker := time.NewTicker(fs.usageCheckInterval)
|
||||
defer ticker.Stop()
|
||||
|
||||
usageFn := func(ctx context.Context, entry string) error {
|
||||
var fi os.FileInfo
|
||||
var err error
|
||||
if hasSuffix(entry, slashSeparator) {
|
||||
fi, err = fsStatDir(ctx, entry)
|
||||
} else {
|
||||
fi, err = fsStatFile(ctx, entry)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
atomic.AddUint64(&fs.totalUsed, uint64(fi.Size()))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := getDiskUsage(context.Background(), fs.fsPath, usageFn); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-doneCh:
|
||||
return
|
||||
case <-ticker.C:
|
||||
var usage uint64
|
||||
usageFn = func(ctx context.Context, entry string) error {
|
||||
var fi os.FileInfo
|
||||
var err error
|
||||
if hasSuffix(entry, slashSeparator) {
|
||||
fi, err = fsStatDir(ctx, entry)
|
||||
} else {
|
||||
fi, err = fsStatFile(ctx, entry)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
usage = usage + uint64(fi.Size())
|
||||
return nil
|
||||
}
|
||||
if err := getDiskUsage(context.Background(), fs.fsPath, usageFn); err != nil {
|
||||
continue
|
||||
}
|
||||
atomic.StoreUint64(&fs.totalUsed, usage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StorageInfo - returns underlying storage statistics.
|
||||
func (fs *FSObjects) StorageInfo(ctx context.Context) StorageInfo {
|
||||
info, err := getDiskInfo((fs.fsPath))
|
||||
logger.GetReqInfo(ctx).AppendTags("path", fs.fsPath)
|
||||
logger.LogIf(ctx, err)
|
||||
storageInfo := StorageInfo{
|
||||
Total: info.Total,
|
||||
Free: info.Free,
|
||||
Used: atomic.LoadUint64(&fs.totalUsed),
|
||||
}
|
||||
storageInfo.Backend.Type = FS
|
||||
return storageInfo
|
||||
|
||||
+5
-4
@@ -33,6 +33,11 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logger.Init(GOPATH)
|
||||
logger.RegisterUIError(fmtError)
|
||||
}
|
||||
|
||||
var (
|
||||
gatewayCmd = cli.Command{
|
||||
Name: "gateway",
|
||||
@@ -102,10 +107,6 @@ func ValidateGatewayArguments(serverAddr, endpointAddr string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
logger.Init(GOPATH)
|
||||
}
|
||||
|
||||
// StartGateway - handler for 'minio gateway <name>'.
|
||||
func StartGateway(ctx *cli.Context, gw Gateway) {
|
||||
if gw == nil {
|
||||
|
||||
@@ -75,36 +75,32 @@ ENVIRONMENT VARIABLES:
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";".
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";".
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days.
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for Azure Blob Storage backend.
|
||||
$ export MINIO_ACCESS_KEY=azureaccountname
|
||||
$ export MINIO_SECRET_KEY=azureaccountkey
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=azureaccountname
|
||||
$ export MINIO_SECRET_KEY=azureaccountkey
|
||||
$ {{.HelpName}}
|
||||
|
||||
2. Start minio gateway server for Azure Blob Storage backend on custom endpoint.
|
||||
$ export MINIO_ACCESS_KEY=azureaccountname
|
||||
$ export MINIO_SECRET_KEY=azureaccountkey
|
||||
$ {{.HelpName}} https://azure.example.com
|
||||
$ export MINIO_ACCESS_KEY=azureaccountname
|
||||
$ export MINIO_SECRET_KEY=azureaccountkey
|
||||
$ {{.HelpName}} https://azure.example.com
|
||||
|
||||
3. Start minio gateway server for Azure Blob Storage backend with edge caching enabled.
|
||||
$ export MINIO_ACCESS_KEY=azureaccountname
|
||||
$ export MINIO_SECRET_KEY=azureaccountkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
|
||||
$ export MINIO_ACCESS_KEY=azureaccountname
|
||||
$ export MINIO_SECRET_KEY=azureaccountkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
`
|
||||
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
|
||||
@@ -65,30 +65,27 @@ ENVIRONMENT VARIABLES:
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";".
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";".
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days.
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for B2 backend.
|
||||
$ export MINIO_ACCESS_KEY=accountID
|
||||
$ export MINIO_SECRET_KEY=applicationKey
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=accountID
|
||||
$ export MINIO_SECRET_KEY=applicationKey
|
||||
$ {{.HelpName}}
|
||||
|
||||
2. Start minio gateway server for B2 backend with edge caching enabled.
|
||||
$ export MINIO_ACCESS_KEY=accountID
|
||||
$ export MINIO_SECRET_KEY=applicationKey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=accountID
|
||||
$ export MINIO_SECRET_KEY=applicationKey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
`
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
Name: b2Backend,
|
||||
|
||||
@@ -111,36 +111,33 @@ ENVIRONMENT VARIABLES:
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";".
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";".
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days.
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
GCS credentials file:
|
||||
GOOGLE_APPLICATION_CREDENTIALS: Path to credentials.json
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for GCS backend.
|
||||
$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
|
||||
(Instructions to generate credentials : https://developers.google.com/identity/protocols/application-default-credentials)
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}} mygcsprojectid
|
||||
$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
|
||||
(Instructions to generate credentials : https://developers.google.com/identity/protocols/application-default-credentials)
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}} mygcsprojectid
|
||||
|
||||
2. Start minio gateway server for GCS backend with edge caching enabled.
|
||||
$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}} mygcsprojectid
|
||||
$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}} mygcsprojectid
|
||||
`
|
||||
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
|
||||
@@ -81,28 +81,28 @@ ENVIRONMENT VARIABLES:
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for Manta Object Storage backend.
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ {{.HelpName}}
|
||||
|
||||
2. Start minio gateway server for Manta Object Storage backend on custom endpoint.
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ {{.HelpName}} https://us-west.manta.joyent.com
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ {{.HelpName}} https://us-west.manta.joyent.com
|
||||
|
||||
3. Start minio gateway server for Manta Object Storage backend without using SSH Agent.
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ export MANTA_KEY_MATERIAL=~/.ssh/custom_rsa
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ export MANTA_KEY_MATERIAL=~/.ssh/custom_rsa
|
||||
$ {{.HelpName}}
|
||||
|
||||
4. Start minio gateway server for Manta Object Storage backend with edge caching enabled.
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=manta_account_name
|
||||
$ export MINIO_SECRET_KEY=manta_key_id
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
`
|
||||
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
|
||||
@@ -40,7 +40,7 @@ FLAGS:
|
||||
{{range .VisibleFlags}}{{.}}
|
||||
{{end}}{{end}}
|
||||
PATH:
|
||||
path to NAS mount point.
|
||||
Path to NAS mount point.
|
||||
|
||||
ENVIRONMENT VARIABLES:
|
||||
ACCESS:
|
||||
@@ -50,30 +50,27 @@ ENVIRONMENT VARIABLES:
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";".
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";".
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days.
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for NAS backend.
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}} /shared/nasvol
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}} /shared/nasvol
|
||||
|
||||
2. Start minio gateway server for NAS with edge caching enabled.
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}} /shared/nasvol
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}} /shared/nasvol
|
||||
`
|
||||
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
|
||||
@@ -67,9 +67,6 @@ ENVIRONMENT VARIABLES:
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
@@ -80,22 +77,22 @@ ENVIRONMENT VARIABLES:
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for Aliyun OSS backend.
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}}
|
||||
|
||||
2. Start minio gateway server for Aliyun OSS backend on custom endpoint.
|
||||
$ export MINIO_ACCESS_KEY=Q3AM3UQ867SPQQA43P2F
|
||||
$ export MINIO_SECRET_KEY=zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
|
||||
$ {{.HelpName}} https://oss.example.com
|
||||
$ export MINIO_ACCESS_KEY=Q3AM3UQ867SPQQA43P2F
|
||||
$ export MINIO_SECRET_KEY=zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
|
||||
$ {{.HelpName}} https://oss.example.com
|
||||
|
||||
3. Start minio gateway server for Aliyun OSS backend with edge caching enabled.
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
`
|
||||
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
|
||||
@@ -58,35 +58,32 @@ ENVIRONMENT VARIABLES:
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";".
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";".
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days.
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for AWS S3 backend.
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ {{.HelpName}}
|
||||
|
||||
2. Start minio gateway server for S3 backend on custom endpoint.
|
||||
$ export MINIO_ACCESS_KEY=Q3AM3UQ867SPQQA43P2F
|
||||
$ export MINIO_SECRET_KEY=zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
|
||||
$ {{.HelpName}} https://play.minio.io:9000
|
||||
$ export MINIO_ACCESS_KEY=Q3AM3UQ867SPQQA43P2F
|
||||
$ export MINIO_SECRET_KEY=zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
|
||||
$ {{.HelpName}} https://play.minio.io:9000
|
||||
|
||||
3. Start minio gateway server for AWS S3 backend with edge caching enabled.
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
`
|
||||
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
|
||||
@@ -72,29 +72,26 @@ ENVIRONMENT VARIABLES: (Default values in parenthesis)
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of mounted drives or directories delimited by ";".
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";".
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days.
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
SIA_TEMP_DIR: The name of the local Sia temporary storage directory. (.sia_temp)
|
||||
SIA_API_PASSWORD: API password for Sia daemon. (default is empty)
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio gateway server for Sia backend.
|
||||
$ {{.HelpName}}
|
||||
$ {{.HelpName}}
|
||||
|
||||
2. Start minio gateway server for Sia backend with edge caching enabled.
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
`
|
||||
|
||||
minio.RegisterGatewayCommand(cli.Command{
|
||||
|
||||
@@ -190,8 +190,6 @@ func (st *HTTPStats) updateStats(r *http.Request, w *httpResponseRecorder, durat
|
||||
st.successDELETEs.Duration.Add(durationSecs)
|
||||
}
|
||||
}
|
||||
// Increment the prometheus http request count with appropriate label
|
||||
httpRequests.With(prometheus.Labels{"request_type": r.Method}).Inc()
|
||||
// Increment the prometheus http request response histogram with appropriate label
|
||||
httpRequestsDuration.With(prometheus.Labels{"request_type": r.Method}).Observe(durationSecs)
|
||||
}
|
||||
|
||||
+2
-21
@@ -26,13 +26,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
httpRequests = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "minio_http_requests_total",
|
||||
Help: "Total number of requests served by current Minio server instance",
|
||||
},
|
||||
[]string{"request_type"},
|
||||
)
|
||||
httpRequestsDuration = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "minio_http_requests_duration_seconds",
|
||||
@@ -44,7 +37,6 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(httpRequests)
|
||||
prometheus.MustRegister(httpRequestsDuration)
|
||||
prometheus.MustRegister(newMinioCollector())
|
||||
}
|
||||
@@ -107,6 +99,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
prometheus.CounterValue,
|
||||
float64(globalConnStats.getTotalInputBytes()),
|
||||
)
|
||||
|
||||
// Total/Free Storage Bytes
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
prometheus.NewDesc(
|
||||
@@ -124,15 +117,6 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
prometheus.GaugeValue,
|
||||
float64(s.Free),
|
||||
)
|
||||
// Set Server Start Time
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
prometheus.NewDesc(
|
||||
prometheus.BuildFQName("minio", "server", "start_time_seconds"),
|
||||
"Time when current Minio server instance started",
|
||||
nil, nil),
|
||||
prometheus.GaugeValue,
|
||||
float64(globalBootTime.Unix()),
|
||||
)
|
||||
|
||||
// Minio Total Disk/Offline Disk
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
@@ -156,10 +140,7 @@ func (c *minioCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
func metricsHandler() http.Handler {
|
||||
registry := prometheus.NewRegistry()
|
||||
|
||||
err := registry.Register(httpRequests)
|
||||
logger.LogIf(context.Background(), err)
|
||||
|
||||
err = registry.Register(httpRequestsDuration)
|
||||
err := registry.Register(httpRequestsDuration)
|
||||
logger.LogIf(context.Background(), err)
|
||||
|
||||
err = registry.Register(newMinioCollector())
|
||||
|
||||
@@ -18,8 +18,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
// naughtyDisk wraps a POSIX disk and returns programmed errors
|
||||
@@ -74,7 +72,7 @@ func (d *naughtyDisk) calcError() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *naughtyDisk) DiskInfo() (info disk.Info, err error) {
|
||||
func (d *naughtyDisk) DiskInfo() (info DiskInfo, err error) {
|
||||
if err := d.calcError(); err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@ const (
|
||||
|
||||
// StorageInfo - represents total capacity of underlying storage.
|
||||
type StorageInfo struct {
|
||||
// Total disk space.
|
||||
Total uint64
|
||||
// Free available disk space.
|
||||
Free uint64
|
||||
Total uint64 // Total disk space.
|
||||
Free uint64 // Free available space.
|
||||
Used uint64 // Used total used per tenant.
|
||||
|
||||
// Backend type.
|
||||
Backend struct {
|
||||
// Represents various backend types, currently on FS and Erasure.
|
||||
|
||||
+85
-4
@@ -29,6 +29,7 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
@@ -47,6 +48,11 @@ type posix struct {
|
||||
diskPath string
|
||||
pool sync.Pool
|
||||
connected bool
|
||||
|
||||
// Disk usage metrics
|
||||
stopUsageCh chan struct{}
|
||||
totalUsage uint64
|
||||
usageCheckInterval time.Duration
|
||||
}
|
||||
|
||||
// checkPathLength - returns error if given path name length more than 255
|
||||
@@ -72,7 +78,7 @@ func checkPathLength(pathName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkPathValid(path string) (string, error) {
|
||||
func getValidPath(path string) (string, error) {
|
||||
if path == "" {
|
||||
return path, errInvalidArgument
|
||||
}
|
||||
@@ -128,6 +134,7 @@ func isDirEmpty(dirname string) bool {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// List one entry.
|
||||
_, err = f.Readdirnames(1)
|
||||
if err != io.EOF {
|
||||
@@ -144,7 +151,7 @@ func isDirEmpty(dirname string) bool {
|
||||
// Initialize a new storage disk.
|
||||
func newPosix(path string) (StorageAPI, error) {
|
||||
var err error
|
||||
if path, err = checkPathValid(path); err != nil {
|
||||
if path, err = getValidPath(path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -157,9 +164,14 @@ func newPosix(path string) (StorageAPI, error) {
|
||||
return &b
|
||||
},
|
||||
},
|
||||
stopUsageCh: make(chan struct{}),
|
||||
usageCheckInterval: usageCheckInterval,
|
||||
}
|
||||
|
||||
st.connected = true
|
||||
|
||||
go st.diskUsage()
|
||||
|
||||
// Success.
|
||||
return st, nil
|
||||
}
|
||||
@@ -242,6 +254,7 @@ func (s *posix) String() string {
|
||||
}
|
||||
|
||||
func (s *posix) Close() error {
|
||||
close(s.stopUsageCh)
|
||||
s.connected = false
|
||||
return nil
|
||||
}
|
||||
@@ -250,10 +263,26 @@ func (s *posix) IsOnline() bool {
|
||||
return s.connected
|
||||
}
|
||||
|
||||
// DiskInfo is an extended type which returns current
|
||||
// disk usage per path.
|
||||
type DiskInfo struct {
|
||||
Total uint64
|
||||
Free uint64
|
||||
Used uint64
|
||||
}
|
||||
|
||||
// DiskInfo provides current information about disk space usage,
|
||||
// total free inodes and underlying filesystem.
|
||||
func (s *posix) DiskInfo() (info disk.Info, err error) {
|
||||
return getDiskInfo((s.diskPath))
|
||||
func (s *posix) DiskInfo() (info DiskInfo, err error) {
|
||||
di, err := getDiskInfo(s.diskPath)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
return DiskInfo{
|
||||
Total: di.Total,
|
||||
Free: di.Free,
|
||||
Used: atomic.LoadUint64(&s.totalUsage),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getVolDir - will convert incoming volume names to
|
||||
@@ -285,6 +314,58 @@ func (s *posix) checkDiskFound() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// diskUsage returns du information for the posix path, in a continuous routine.
|
||||
func (s *posix) diskUsage() {
|
||||
ticker := time.NewTicker(s.usageCheckInterval)
|
||||
defer ticker.Stop()
|
||||
|
||||
usageFn := func(ctx context.Context, entry string) error {
|
||||
select {
|
||||
case <-s.stopUsageCh:
|
||||
return errWalkAbort
|
||||
default:
|
||||
fi, err := os.Stat(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
atomic.AddUint64(&s.totalUsage, uint64(fi.Size()))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := getDiskUsage(context.Background(), s.diskPath, usageFn); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-s.stopUsageCh:
|
||||
return
|
||||
case <-globalServiceDoneCh:
|
||||
return
|
||||
case <-ticker.C:
|
||||
var usage uint64
|
||||
usageFn = func(ctx context.Context, entry string) error {
|
||||
select {
|
||||
case <-s.stopUsageCh:
|
||||
return errWalkAbort
|
||||
default:
|
||||
fi, err := os.Stat(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
usage = usage + uint64(fi.Size())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := getDiskUsage(context.Background(), s.diskPath, usageFn); err != nil {
|
||||
continue
|
||||
}
|
||||
atomic.StoreUint64(&s.totalUsage, usage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make a volume entry.
|
||||
func (s *posix) MakeVol(volume string) (err error) {
|
||||
defer func() {
|
||||
|
||||
+39
-25
@@ -22,6 +22,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/minio/cli"
|
||||
@@ -30,6 +31,11 @@ import (
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logger.Init(GOPATH)
|
||||
logger.RegisterUIError(fmtError)
|
||||
}
|
||||
|
||||
var serverFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "address",
|
||||
@@ -65,6 +71,9 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_ACCESS_KEY: Custom username or access key of minimum 3 characters in length.
|
||||
MINIO_SECRET_KEY: Custom password or secret key of minimum 8 characters in length.
|
||||
|
||||
ENDPOINTS:
|
||||
MINIO_ENDPOINTS: List of all endpoints delimited by ' '.
|
||||
|
||||
BROWSER:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
@@ -73,12 +82,6 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";".
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days.
|
||||
|
||||
REGION:
|
||||
MINIO_REGION: To set custom region. By default all regions are accepted.
|
||||
|
||||
UPDATE:
|
||||
MINIO_UPDATE: To turn off in-place upgrades, set this value to "off".
|
||||
|
||||
DOMAIN:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
@@ -87,23 +90,24 @@ ENVIRONMENT VARIABLES:
|
||||
|
||||
EXAMPLES:
|
||||
1. Start minio server on "/home/shared" directory.
|
||||
$ {{.HelpName}} /home/shared
|
||||
$ {{.HelpName}} /home/shared
|
||||
|
||||
2. Start minio server bound to a specific ADDRESS:PORT.
|
||||
$ {{.HelpName}} --address 192.168.1.101:9000 /home/shared
|
||||
$ {{.HelpName}} --address 192.168.1.101:9000 /home/shared
|
||||
|
||||
3. Start minio server and enable virtual-host-style requests.
|
||||
$ export MINIO_DOMAIN=mydomain.com
|
||||
$ {{.HelpName}} --address mydomain.com:9000 /mnt/export
|
||||
$ export MINIO_DOMAIN=mydomain.com
|
||||
$ {{.HelpName}} --address mydomain.com:9000 /mnt/export
|
||||
|
||||
4. Start minio server on 64 disks server.
|
||||
$ {{.HelpName}} /mnt/export{1...64}
|
||||
4. Start minio server on 64 disks server with endpoints through environment variable.
|
||||
$ export MINIO_ENDPOINTS=/mnt/export{1...64}
|
||||
$ {{.HelpName}}
|
||||
|
||||
5. Start distributed minio server on an 8 node setup with 8 drives each. Run following command on all the 8 nodes.
|
||||
$ export MINIO_ACCESS_KEY=minio
|
||||
$ export MINIO_SECRET_KEY=miniostorage
|
||||
$ {{.HelpName}} http://node{1...8}.example.com/mnt/export/{1...8}
|
||||
|
||||
$ export MINIO_ACCESS_KEY=minio
|
||||
$ export MINIO_SECRET_KEY=miniostorage
|
||||
$ {{.HelpName}} http://node{1...8}.example.com/mnt/export/{1...8}
|
||||
|
||||
6. Start minio server with edge caching enabled.
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
@@ -112,6 +116,16 @@ EXAMPLES:
|
||||
`,
|
||||
}
|
||||
|
||||
// Checks if endpoints are either available through environment
|
||||
// or command line, returns false if both fails.
|
||||
func endpointsPresent(ctx *cli.Context) bool {
|
||||
_, ok := os.LookupEnv("MINIO_ENDPOINTS")
|
||||
if !ok {
|
||||
ok = ctx.Args().Present()
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func serverHandleCmdArgs(ctx *cli.Context) {
|
||||
// Handle common command args.
|
||||
handleCommonCmdArgs(ctx)
|
||||
@@ -124,11 +138,17 @@ func serverHandleCmdArgs(ctx *cli.Context) {
|
||||
var err error
|
||||
|
||||
if len(ctx.Args()) > serverCommandLineArgsMax {
|
||||
uErr := uiErrInvalidErasureEndpoints(nil).Msg(fmt.Sprintf("Invalid total number of endpoints (%d) passed, supported upto 32 unique arguments", len(ctx.Args())))
|
||||
uErr := uiErrInvalidErasureEndpoints(nil).Msg(fmt.Sprintf("Invalid total number of endpoints (%d) passed, supported upto 32 unique arguments",
|
||||
len(ctx.Args())))
|
||||
logger.FatalIf(uErr, "Unable to validate passed endpoints")
|
||||
}
|
||||
|
||||
globalMinioAddr, globalEndpoints, setupType, globalXLSetCount, globalXLSetDriveCount, err = createServerEndpoints(serverAddr, ctx.Args()...)
|
||||
endpoints := strings.Fields(os.Getenv("MINIO_ENDPOINTS"))
|
||||
if len(endpoints) > 0 {
|
||||
globalMinioAddr, globalEndpoints, setupType, globalXLSetCount, globalXLSetDriveCount, err = createServerEndpoints(serverAddr, endpoints...)
|
||||
} else {
|
||||
globalMinioAddr, globalEndpoints, setupType, globalXLSetCount, globalXLSetDriveCount, err = createServerEndpoints(serverAddr, ctx.Args()...)
|
||||
}
|
||||
logger.FatalIf(err, "Invalid command line arguments")
|
||||
|
||||
globalMinioHost, globalMinioPort = mustSplitHostPort(globalMinioAddr)
|
||||
@@ -158,13 +178,9 @@ func serverHandleEnvVars() {
|
||||
|
||||
}
|
||||
|
||||
func init() {
|
||||
logger.Init(GOPATH)
|
||||
}
|
||||
|
||||
// serverMain handler called for 'minio server' command.
|
||||
func serverMain(ctx *cli.Context) {
|
||||
if (!ctx.IsSet("sets") && !ctx.Args().Present()) || ctx.Args().First() == "help" {
|
||||
if ctx.Args().First() == "help" || !endpointsPresent(ctx) {
|
||||
cli.ShowCommandHelpAndExit(ctx, "server", 1)
|
||||
}
|
||||
|
||||
@@ -185,8 +201,6 @@ func serverMain(ctx *cli.Context) {
|
||||
logger.EnableQuiet()
|
||||
}
|
||||
|
||||
logger.RegisterUIError(fmtError)
|
||||
|
||||
// Handle all server command args.
|
||||
serverHandleCmdArgs(ctx)
|
||||
|
||||
|
||||
@@ -173,19 +173,19 @@ func printObjectAPIMsg() {
|
||||
|
||||
// Get formatted disk/storage info message.
|
||||
func getStorageInfoMsg(storageInfo StorageInfo) string {
|
||||
msg := fmt.Sprintf("%s %s Free, %s Total", colorBlue("Drive Capacity:"),
|
||||
humanize.IBytes(uint64(storageInfo.Free)),
|
||||
humanize.IBytes(uint64(storageInfo.Total)))
|
||||
var msg string
|
||||
if storageInfo.Backend.Type == Erasure {
|
||||
diskInfo := fmt.Sprintf(" %d Online, %d Offline. ", storageInfo.Backend.OnlineDisks, storageInfo.Backend.OfflineDisks)
|
||||
msg += colorBlue("\nStatus:") + fmt.Sprintf(getFormatStr(len(diskInfo), 8), diskInfo)
|
||||
msg += colorBlue("Status:") + fmt.Sprintf(getFormatStr(len(diskInfo), 8), diskInfo)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// Prints startup message of storage capacity and erasure information.
|
||||
func printStorageInfo(storageInfo StorageInfo) {
|
||||
logger.StartupMessage(getStorageInfoMsg(storageInfo) + "\n")
|
||||
if msg := getStorageInfoMsg(storageInfo); msg != "" {
|
||||
logger.StartupMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func printCacheStorageInfo(storageInfo StorageInfo) {
|
||||
|
||||
@@ -25,20 +25,16 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
// Tests if we generate storage info.
|
||||
func TestStorageInfoMsg(t *testing.T) {
|
||||
infoStorage := StorageInfo{}
|
||||
infoStorage.Total = 10 * humanize.GiByte
|
||||
infoStorage.Free = 2 * humanize.GiByte
|
||||
infoStorage.Backend.Type = Erasure
|
||||
infoStorage.Backend.OnlineDisks = 7
|
||||
infoStorage.Backend.OfflineDisks = 1
|
||||
|
||||
if msg := getStorageInfoMsg(infoStorage); !strings.Contains(msg, "2.0 GiB Free, 10 GiB Total") || !strings.Contains(msg, "7 Online, 1 Offline") {
|
||||
if msg := getStorageInfoMsg(infoStorage); !strings.Contains(msg, "7 Online, 1 Offline") {
|
||||
t.Fatal("Unexpected storage info message, found:", msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
// StorageAPI interface.
|
||||
@@ -30,7 +28,7 @@ type StorageAPI interface {
|
||||
// Storage operations.
|
||||
IsOnline() bool // Returns true if disk is online.
|
||||
Close() error
|
||||
DiskInfo() (info disk.Info, err error)
|
||||
DiskInfo() (info DiskInfo, err error)
|
||||
|
||||
// Volume operations.
|
||||
MakeVol(volume string) (err error)
|
||||
|
||||
@@ -23,8 +23,6 @@ import (
|
||||
"net/rpc"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
type networkStorage struct {
|
||||
@@ -164,10 +162,10 @@ func (n *networkStorage) call(handler string, args interface {
|
||||
}
|
||||
|
||||
// DiskInfo - fetch disk information for a remote disk.
|
||||
func (n *networkStorage) DiskInfo() (info disk.Info, err error) {
|
||||
func (n *networkStorage) DiskInfo() (info DiskInfo, err error) {
|
||||
args := AuthRPCArgs{}
|
||||
if err = n.call("Storage.DiskInfoHandler", &args, &info); err != nil {
|
||||
return disk.Info{}, err
|
||||
return DiskInfo{}, err
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
// Storage server implements rpc primitives to facilitate exporting a
|
||||
@@ -39,7 +38,7 @@ type storageServer struct {
|
||||
/// Storage operations handlers.
|
||||
|
||||
// DiskInfoHandler - disk info handler is rpc wrapper for DiskInfo operation.
|
||||
func (s *storageServer) DiskInfoHandler(args *AuthRPCArgs, reply *disk.Info) error {
|
||||
func (s *storageServer) DiskInfoHandler(args *AuthRPCArgs, reply *DiskInfo) error {
|
||||
if err := args.IsAuthenticated(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ package cmd
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
type testStorageRPCServer struct {
|
||||
@@ -91,7 +89,7 @@ func TestStorageRPCInvalidToken(t *testing.T) {
|
||||
Vol: "myvol",
|
||||
}
|
||||
// 1. DiskInfoHandler
|
||||
diskInfoReply := &disk.Info{}
|
||||
diskInfoReply := &DiskInfo{}
|
||||
err = storageRPC.DiskInfoHandler(&badAuthRPCArgs, diskInfoReply)
|
||||
errorIfInvalidToken(t, err)
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
)
|
||||
|
||||
// Tree walk result carries results of tree walking.
|
||||
@@ -147,7 +145,6 @@ func doTreeWalk(ctx context.Context, bucket, prefixDir, entryPrefixMatch, marker
|
||||
if err != nil {
|
||||
select {
|
||||
case <-endWalkCh:
|
||||
logger.LogIf(ctx, errWalkAbort)
|
||||
return errWalkAbort
|
||||
case resultCh <- treeWalkResult{err: err}:
|
||||
return err
|
||||
@@ -229,7 +226,6 @@ func doTreeWalk(ctx context.Context, bucket, prefixDir, entryPrefixMatch, marker
|
||||
isEOF := ((i == len(entries)-1) && isEnd)
|
||||
select {
|
||||
case <-endWalkCh:
|
||||
logger.LogIf(ctx, errWalkAbort)
|
||||
return errWalkAbort
|
||||
case resultCh <- treeWalkResult{entry: pathJoin(prefixDir, entry), end: isEOF}:
|
||||
}
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ EXIT STATUS:
|
||||
|
||||
EXAMPLES:
|
||||
1. Check and update minio:
|
||||
$ {{.HelpName}}
|
||||
$ {{.HelpName}}
|
||||
`,
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ FLAGS:
|
||||
{{end}}{{end}}
|
||||
EXAMPLES:
|
||||
1. Prints server version:
|
||||
$ {{.HelpName}}
|
||||
$ {{.HelpName}}
|
||||
`,
|
||||
}
|
||||
|
||||
|
||||
@@ -221,13 +221,9 @@ func testStorageInfoWebHandler(obj ObjectLayer, instanceType string, t TestErrHa
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code)
|
||||
}
|
||||
err = getTestWebRPCResponse(rec, &storageInfoReply)
|
||||
if err != nil {
|
||||
if err = getTestWebRPCResponse(rec, &storageInfoReply); err != nil {
|
||||
t.Fatalf("Failed %v", err)
|
||||
}
|
||||
if storageInfoReply.StorageInfo.Total <= 0 {
|
||||
t.Fatalf("Got a zero or negative total free space disk")
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper for calling ServerInfo Web Handler
|
||||
|
||||
+1
-2
@@ -280,8 +280,7 @@ func (s *xlSets) StorageInfo(ctx context.Context) StorageInfo {
|
||||
storageInfo.Backend.Type = Erasure
|
||||
for _, set := range s.sets {
|
||||
lstorageInfo := set.StorageInfo(ctx)
|
||||
storageInfo.Total = storageInfo.Total + lstorageInfo.Total
|
||||
storageInfo.Free = storageInfo.Free + lstorageInfo.Free
|
||||
storageInfo.Used = storageInfo.Used + lstorageInfo.Used
|
||||
storageInfo.Backend.OnlineDisks = storageInfo.Backend.OnlineDisks + lstorageInfo.Backend.OnlineDisks
|
||||
storageInfo.Backend.OfflineDisks = storageInfo.Backend.OfflineDisks + lstorageInfo.Backend.OfflineDisks
|
||||
}
|
||||
|
||||
@@ -98,46 +98,6 @@ func TestNewXLSets(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestStorageInfoSets - tests storage info for erasure coded sets of disks.
|
||||
func TestStorageInfoSets(t *testing.T) {
|
||||
var nDisks = 16 // Maximum disks.
|
||||
var erasureDisks []string
|
||||
for i := 0; i < nDisks; i++ {
|
||||
// Do not attempt to create this path, the test validates
|
||||
// so that newXLSets initializes non existing paths
|
||||
// and successfully returns initialized object layer.
|
||||
disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix())
|
||||
erasureDisks = append(erasureDisks, disk)
|
||||
defer os.RemoveAll(disk)
|
||||
}
|
||||
|
||||
endpoints := mustGetNewEndpointList(erasureDisks...)
|
||||
// Initializes all erasure disks
|
||||
format, err := waitForFormatXL(context.Background(), true, endpoints, 1, 16)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to format disks for erasure, %s", err)
|
||||
}
|
||||
|
||||
objLayer, err := newXLSets(endpoints, format, 1, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Get storage info first attempt.
|
||||
disks16Info := objLayer.StorageInfo(context.Background())
|
||||
|
||||
// This test assumes homogeneity between all disks,
|
||||
// i.e if we loose one disk the effective storage
|
||||
// usage values is assumed to decrease. If we have
|
||||
// heterogenous environment this is not true all the time.
|
||||
if disks16Info.Free <= 0 {
|
||||
t.Fatalf("Diskinfo total free values should be greater 0")
|
||||
}
|
||||
if disks16Info.Total <= 0 {
|
||||
t.Fatalf("Diskinfo total values should be greater 0")
|
||||
}
|
||||
}
|
||||
|
||||
// TestHashedLayer - tests the hashed layer which will be returned
|
||||
// consistently for a given object name.
|
||||
func TestHashedLayer(t *testing.T) {
|
||||
|
||||
+13
-16
@@ -23,7 +23,6 @@ import (
|
||||
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
"github.com/minio/minio/pkg/bpool"
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
// XL constants.
|
||||
@@ -118,7 +117,7 @@ func (xl xlObjects) ClearLocks(ctx context.Context, volLocks []VolumeLockInfo) e
|
||||
}
|
||||
|
||||
// byDiskTotal is a collection satisfying sort.Interface.
|
||||
type byDiskTotal []disk.Info
|
||||
type byDiskTotal []DiskInfo
|
||||
|
||||
func (d byDiskTotal) Len() int { return len(d) }
|
||||
func (d byDiskTotal) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
||||
@@ -127,8 +126,8 @@ func (d byDiskTotal) Less(i, j int) bool {
|
||||
}
|
||||
|
||||
// getDisksInfo - fetch disks info across all other storage API.
|
||||
func getDisksInfo(disks []StorageAPI) (disksInfo []disk.Info, onlineDisks int, offlineDisks int) {
|
||||
disksInfo = make([]disk.Info, len(disks))
|
||||
func getDisksInfo(disks []StorageAPI) (disksInfo []DiskInfo, onlineDisks int, offlineDisks int) {
|
||||
disksInfo = make([]DiskInfo, len(disks))
|
||||
for i, storageDisk := range disks {
|
||||
if storageDisk == nil {
|
||||
// Storage disk is empty, perhaps ignored disk or not available.
|
||||
@@ -154,8 +153,8 @@ func getDisksInfo(disks []StorageAPI) (disksInfo []disk.Info, onlineDisks int, o
|
||||
// returns sorted disksInfo slice which has only valid entries.
|
||||
// i.e the entries where the total size of the disk is not stated
|
||||
// as 0Bytes, this means that the disk is not online or ignored.
|
||||
func sortValidDisksInfo(disksInfo []disk.Info) []disk.Info {
|
||||
var validDisksInfo []disk.Info
|
||||
func sortValidDisksInfo(disksInfo []DiskInfo) []DiskInfo {
|
||||
var validDisksInfo []DiskInfo
|
||||
for _, diskInfo := range disksInfo {
|
||||
if diskInfo.Total == 0 {
|
||||
continue
|
||||
@@ -174,10 +173,7 @@ func getStorageInfo(disks []StorageAPI) StorageInfo {
|
||||
validDisksInfo := sortValidDisksInfo(disksInfo)
|
||||
// If there are no valid disks, set total and free disks to 0
|
||||
if len(validDisksInfo) == 0 {
|
||||
return StorageInfo{
|
||||
Total: 0,
|
||||
Free: 0,
|
||||
}
|
||||
return StorageInfo{}
|
||||
}
|
||||
|
||||
_, sscParity := getRedundancyCount(standardStorageClass, len(disks))
|
||||
@@ -193,13 +189,14 @@ func getStorageInfo(disks []StorageAPI) StorageInfo {
|
||||
availableDataDisks = uint64(onlineDisks)
|
||||
}
|
||||
|
||||
// Return calculated storage info, choose the lowest Total and
|
||||
// Free as the total aggregated values. Total capacity is always
|
||||
// the multiple of smallest disk among the disk list.
|
||||
storageInfo := StorageInfo{
|
||||
Total: validDisksInfo[0].Total * availableDataDisks,
|
||||
Free: validDisksInfo[0].Free * availableDataDisks,
|
||||
storageInfo := StorageInfo{}
|
||||
|
||||
// Combine all disks to get total usage.
|
||||
var used uint64
|
||||
for _, di := range validDisksInfo {
|
||||
used = used + di.Used
|
||||
}
|
||||
storageInfo.Used = used
|
||||
|
||||
storageInfo.Backend.Type = Erasure
|
||||
storageInfo.Backend.OnlineDisks = onlineDisks
|
||||
|
||||
+6
-37
@@ -17,56 +17,25 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
// TestStorageInfo - tests storage info.
|
||||
func TestStorageInfo(t *testing.T) {
|
||||
objLayer, fsDirs, err := prepareXL16()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to initialize 'XL' object layer.")
|
||||
}
|
||||
|
||||
// Remove all dirs.
|
||||
for _, dir := range fsDirs {
|
||||
defer os.RemoveAll(dir)
|
||||
}
|
||||
|
||||
// Get storage info first attempt.
|
||||
disks16Info := objLayer.StorageInfo(context.Background())
|
||||
|
||||
// This test assumes homogenity between all disks,
|
||||
// i.e if we loose one disk the effective storage
|
||||
// usage values is assumed to decrease. If we have
|
||||
// heterogenous environment this is not true all the time.
|
||||
if disks16Info.Free <= 0 {
|
||||
t.Fatalf("Diskinfo total free values should be greater 0")
|
||||
}
|
||||
if disks16Info.Total <= 0 {
|
||||
t.Fatalf("Diskinfo total values should be greater 0")
|
||||
}
|
||||
}
|
||||
|
||||
// Sort valid disks info.
|
||||
func TestSortingValidDisks(t *testing.T) {
|
||||
testCases := []struct {
|
||||
disksInfo []disk.Info
|
||||
validDisksInfo []disk.Info
|
||||
disksInfo []DiskInfo
|
||||
validDisksInfo []DiskInfo
|
||||
}{
|
||||
// One of the disks is offline.
|
||||
{
|
||||
disksInfo: []disk.Info{
|
||||
disksInfo: []DiskInfo{
|
||||
{Total: 150, Free: 10},
|
||||
{Total: 0, Free: 0},
|
||||
{Total: 200, Free: 10},
|
||||
{Total: 100, Free: 10},
|
||||
},
|
||||
validDisksInfo: []disk.Info{
|
||||
validDisksInfo: []DiskInfo{
|
||||
{Total: 100, Free: 10},
|
||||
{Total: 150, Free: 10},
|
||||
{Total: 200, Free: 10},
|
||||
@@ -74,13 +43,13 @@ func TestSortingValidDisks(t *testing.T) {
|
||||
},
|
||||
// All disks are online.
|
||||
{
|
||||
disksInfo: []disk.Info{
|
||||
disksInfo: []DiskInfo{
|
||||
{Total: 150, Free: 10},
|
||||
{Total: 200, Free: 10},
|
||||
{Total: 100, Free: 10},
|
||||
{Total: 115, Free: 10},
|
||||
},
|
||||
validDisksInfo: []disk.Info{
|
||||
validDisksInfo: []DiskInfo{
|
||||
{Total: 100, Free: 10},
|
||||
{Total: 115, Free: 10},
|
||||
{Total: 150, Free: 10},
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
## Minio Prometheus Metric
|
||||
|
||||
Minio server exposes an endpoint for Promethueus to scrape server data at `/minio/prometheus/metrics`.
|
||||
|
||||
### Prometheus probe
|
||||
Prometheus is used to monitor Minio server information like http request, disk storage, network stats etc.. It uses a config file named `prometheus.yaml` to scrape data from server. The value for `metrics_path` and `targets` need to be configured in the config yaml to specify the endpoint and url as shown:
|
||||
```
|
||||
scrape_configs:
|
||||
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
|
||||
- job_name: minio
|
||||
metrics_path: /minio/prometheus/metrics
|
||||
|
||||
# metrics_path defaults to '/metrics'
|
||||
# scheme defaults to 'http'.
|
||||
|
||||
static_configs:
|
||||
- targets: ['localhost:9000']
|
||||
```
|
||||
Prometheus can be run by executing :
|
||||
```
|
||||
./prometheus --config.file=prometheus.yml
|
||||
```
|
||||
|
||||
### List of Minio metric exposed
|
||||
Minio exposes the following list of metric to Prometheus
|
||||
- `minio_disk_storage_bytes` : Total byte count of disk storage available to current Minio server instance
|
||||
- `minio_disk_storage_free_bytes` : Total byte count of free disk storage available to current Minio server instance
|
||||
- `minio_http_requests_duration_seconds_bucket` : The bucket into which observations are counted for creating Histogram
|
||||
- `minio_http_requests_duration_seconds_count` : The count of current number of observations i.e. total HTTP requests (HEAD/GET/PUT/POST/DELETE).
|
||||
- `minio_http_requests_duration_seconds_sum` : The current aggregate time spent servicing all HTTP requests (HEAD/GET/PUT/POST/DELETE) in seconds
|
||||
- `minio_http_requests_total` : Total number of requests served by current Minio server instance
|
||||
- `minio_network_received_bytes_total` : Total number of bytes received by current Minio server instance
|
||||
- `minio_network_sent_bytes_total` : Total number of bytes sent by current Minio server instance
|
||||
- `minio_offline_disks` : Total number of offline disks for current Minio server instance
|
||||
- `minio_total_disks` : Total number of disks for current Minio server instance
|
||||
- `minio_server_start_time_seconds` : Time Unix time in seconds when current Minio server instance started
|
||||
@@ -0,0 +1,20 @@
|
||||
## Minio Monitoring Guide
|
||||
|
||||
Minio server exposes monitoring data over un-authenticated endpoints so monitoring tools can pick the data without you having to share Minio server credentials. This document lists the monitoring endpoints and relevant documentation.
|
||||
|
||||
### Healthcheck Probe
|
||||
|
||||
Minio server has two healthcheck related endpoints, a liveness probe to indicate if server is working fine and a readiness probe to indicate if server is not accepting connections due to heavy load.
|
||||
|
||||
- Liveness probe available at `/minio/health/live`
|
||||
- Readiness probe available at `/minio/health/ready`
|
||||
|
||||
Read more on how to use these endpoints in [Minio healthcheck guide](https://github.com/minio/minio/blob/master/docs/metrics/healthcheck/README.md).
|
||||
|
||||
### Prometheus Probe
|
||||
|
||||
Minio server exposes Prometheus compatible data on a single endpoint.
|
||||
|
||||
- Prometheus data available at `/minio/prometheus/metrics`
|
||||
|
||||
To use this endpoint, setup Prometheus to scrape data from this endpoint. Read more on how to use Prometheues to monitor Minio server in [How to monitor Minio server with Prometheus](https://github.com/minio/cookbook/blob/master/docs/how-to-monitor-minio-with-prometheus.md).
|
||||
@@ -4,11 +4,11 @@ Minio server exposes two un-authenticated, healthcheck endpoints - liveness prob
|
||||
|
||||
### Liveness probe
|
||||
|
||||
This probe is used to identify situations where the server is running but may not behave optimally, i.e. sluggish response or corrupt backend. Such problems can be *only* fixed by a restart.
|
||||
This probe is used to identify situations where the server is running but may not behave optimally, i.e. sluggish response or corrupt back-end. Such problems can be *only* fixed by a restart.
|
||||
|
||||
Internally, Minio liveness probe handler does a ListBuckets call. If successful, the server returns 200 OK, otherwise 503 Service Unavailable.
|
||||
|
||||
When liveness probe fails, Kubernetes like platforms restart the container.
|
||||
When liveness probe fails, Kubernetes like platforms restart the container.
|
||||
|
||||
### Readiness probe
|
||||
|
||||
@@ -5,7 +5,7 @@ version: '2'
|
||||
# 9001 through 9004.
|
||||
services:
|
||||
minio1:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- data1:/data
|
||||
ports:
|
||||
@@ -15,7 +15,7 @@ services:
|
||||
MINIO_SECRET_KEY: minio123
|
||||
command: server http://minio1/data http://minio2/data http://minio3/data http://minio4/data
|
||||
minio2:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- data2:/data
|
||||
ports:
|
||||
@@ -25,7 +25,7 @@ services:
|
||||
MINIO_SECRET_KEY: minio123
|
||||
command: server http://minio1/data http://minio2/data http://minio3/data http://minio4/data
|
||||
minio3:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- data3:/data
|
||||
ports:
|
||||
@@ -35,7 +35,7 @@ services:
|
||||
MINIO_SECRET_KEY: minio123
|
||||
command: server http://minio1/data http://minio2/data http://minio3/data http://minio4/data
|
||||
minio4:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- data4:/data
|
||||
ports:
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3.1'
|
||||
|
||||
services:
|
||||
minio1:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio1-data:/export
|
||||
ports:
|
||||
@@ -20,7 +20,7 @@ services:
|
||||
- access_key
|
||||
|
||||
minio2:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio2-data:/export
|
||||
ports:
|
||||
@@ -38,7 +38,7 @@ services:
|
||||
- access_key
|
||||
|
||||
minio3:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio3-data:/export
|
||||
ports:
|
||||
@@ -56,7 +56,7 @@ services:
|
||||
- access_key
|
||||
|
||||
minio4:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio4-data:/export
|
||||
ports:
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
minio1:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio1-data:/export
|
||||
ports:
|
||||
@@ -20,7 +20,7 @@ services:
|
||||
command: server http://minio1/export http://minio2/export http://minio3/export http://minio4/export
|
||||
|
||||
minio2:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio2-data:/export
|
||||
ports:
|
||||
@@ -38,7 +38,7 @@ services:
|
||||
command: server http://minio1/export http://minio2/export http://minio3/export http://minio4/export
|
||||
|
||||
minio3:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio3-data:/export
|
||||
ports:
|
||||
@@ -56,7 +56,7 @@ services:
|
||||
command: server http://minio1/export http://minio2/export http://minio3/export http://minio4/export
|
||||
|
||||
minio4:
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
volumes:
|
||||
- minio4-data:/export
|
||||
ports:
|
||||
|
||||
@@ -124,7 +124,7 @@ spec:
|
||||
- name: data
|
||||
mountPath: "/data"
|
||||
# Pulls the lastest Minio image from Docker Hub
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
args:
|
||||
- server
|
||||
- /data
|
||||
@@ -303,7 +303,7 @@ spec:
|
||||
value: "minio"
|
||||
- name: MINIO_SECRET_KEY
|
||||
value: "minio123"
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
args:
|
||||
- server
|
||||
- http://minio-0.minio.default.svc.cluster.local/data
|
||||
@@ -514,7 +514,7 @@ spec:
|
||||
containers:
|
||||
- name: minio
|
||||
# Pulls the default Minio image from Docker Hub
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
args:
|
||||
- gateway
|
||||
- gcs
|
||||
|
||||
@@ -21,7 +21,7 @@ spec:
|
||||
value: "minio"
|
||||
- name: MINIO_SECRET_KEY
|
||||
value: "minio123"
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
args:
|
||||
- server
|
||||
- http://minio-0.minio.default.svc.cluster.local/data
|
||||
|
||||
@@ -21,7 +21,7 @@ spec:
|
||||
containers:
|
||||
- name: minio
|
||||
# Pulls the default Minio image from Docker Hub
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
args:
|
||||
- gateway
|
||||
- gcs
|
||||
|
||||
@@ -29,7 +29,7 @@ spec:
|
||||
- name: data
|
||||
mountPath: "/data"
|
||||
# Pulls the lastest Minio image from Docker Hub
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
args:
|
||||
- server
|
||||
- /data
|
||||
|
||||
@@ -30,7 +30,7 @@ Above command deploys Minio on the Kubernetes cluster in the default configurati
|
||||
| Parameter | Description | Default |
|
||||
|----------------------------|-------------------------------------|---------------------------------------------------------|
|
||||
| `image` | Minio image name | `minio/minio` |
|
||||
| `imageTag` | Minio image tag. Possible values listed [here](https://hub.docker.com/r/minio/minio/tags/).| `RELEASE.2018-05-10T00-00-42Z`|
|
||||
| `imageTag` | Minio image tag. Possible values listed [here](https://hub.docker.com/r/minio/minio/tags/).| `RELEASE.2018-05-16T23-35-33Z`|
|
||||
| `imagePullPolicy` | Image pull policy | `Always` |
|
||||
| `mode` | Minio server mode (`standalone`, `shared` or `distributed`)| `standalone` |
|
||||
| `numberOfNodes` | Number of nodes (applicable only for Minio distributed mode). Should be 4 <= x <= 16 | `4` |
|
||||
|
||||
@@ -54,7 +54,7 @@ spec:
|
||||
value: "minio"
|
||||
- name: MINIO_SECRET_KEY
|
||||
value: "minio123"
|
||||
image: minio/minio:RELEASE.2018-05-10T00-00-42Z
|
||||
image: minio/minio:RELEASE.2018-05-16T23-35-33Z
|
||||
imagePullPolicy: IfNotPresent
|
||||
args: ["server", "http://minio-0.minio.default.svc.cluster.local/data", "http://minio-1.minio.default.svc.cluster.local/data", "http://minio-2.minio.default.svc.cluster.local/data", "http://minio-3.minio.default.svc.cluster.local/data"]
|
||||
ports:
|
||||
|
||||
+10
-2
@@ -70,8 +70,16 @@ openssl rsa -in private-pkcs8-key.key -aes256 -passout pass:PASSWORD -out privat
|
||||
|
||||
**Generate the self-signed certificate**:
|
||||
|
||||
Generate self-signed certificate using the below command (remember to replace `<domain.com>` with your actual domain name)
|
||||
|
||||
```sh
|
||||
openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=US/ST=state/L=location/O=organization/CN=domain"
|
||||
openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=US/ST=state/L=location/O=organization/CN=<domain.com>"
|
||||
```
|
||||
|
||||
Generate self-signed wildcard certificate using the below command. This certificate will be valid for all the sub-domains under `domain.com`. Wildcard certificates come in handy while deploying distributed Minio instances where there may be multiple sub-domains under a single domain, with each one running a separate Minio instance.
|
||||
|
||||
```sh
|
||||
openssl req -new -x509 -days 3650 -key private.key -out public.crt -subj "/C=US/ST=state/L=location/O=organization/CN=<*.domain.com>"
|
||||
```
|
||||
|
||||
### Using OpenSSL (with IP address)
|
||||
@@ -179,4 +187,4 @@ Minio can be configured to connect to other servers, whether Minio nodes or serv
|
||||
* [TLS Configuration for Minio server on Kubernetes](https://github.com/minio/minio/tree/master/docs/tls/kubernetes)
|
||||
* [Minio Client Complete Guide](https://docs.minio.io/docs/minio-client-complete-guide)
|
||||
* [Generate Let's Encrypt Certificate](https://docs.minio.io/docs/generate-let-s-encypt-certificate-using-concert-for-minio)
|
||||
* [Setup Nginx Proxy with Minio Server](https://docs.minio.io/docs/setup-nginx-proxy-with-minio)
|
||||
* [Setup nginx Proxy with Minio Server](https://docs.minio.io/docs/setup-nginx-proxy-with-minio)
|
||||
|
||||
@@ -10,6 +10,10 @@ This document explains how to configure Minio server with TLS certificates on Ku
|
||||
|
||||
- Acquire TLS certificates, either from a CA or [create self-signed certificates](https://docs.minio.io/docs/how-to-secure-access-to-minio-server-with-tls).
|
||||
|
||||
For a [distributed Minio setup](https://docs.minio.io/docs/distributed-minio-quickstart-guide), where there are multiple pods with different domain names expected to run, you will either need wildcard certificates valid for all the domains or have specific certificates for each domain. If you are going to use specific certificates, make sure to create Kubernetes secrets accordingly.
|
||||
|
||||
For testing purposes, here is [how to create self-signed certificates](https://github.com/minio/minio/tree/master/docs/tls#3-generate-self-signed-certificates).
|
||||
|
||||
## 2. Create Kubernetes secret
|
||||
|
||||
[Kubernetes secrets](https://kubernetes.io/docs/concepts/configuration/secret) are intended to hold sensitive information.
|
||||
@@ -43,9 +47,9 @@ If you're using certificates provided by a CA, add the below section in your yam
|
||||
secretName: tls-ssl-minio
|
||||
items:
|
||||
- key: public.crt
|
||||
path: .minio/certs/public.crt
|
||||
path: public.crt
|
||||
- key: private.key
|
||||
path: .minio/certs/private.key
|
||||
path: private.key
|
||||
```
|
||||
|
||||
In case you are using a self signed certificate, Minio server will not trust it by default. To add the certificate as a
|
||||
@@ -58,11 +62,11 @@ trusted certificate, add the `public.crt` to the `.minio/certs/CAs` directory as
|
||||
secretName: tls-ssl-minio
|
||||
items:
|
||||
- key: public.crt
|
||||
path: .minio/certs/public.crt
|
||||
path: public.crt
|
||||
- key: private.key
|
||||
path: .minio/certs/private.key
|
||||
path: private.key
|
||||
- key: public.crt
|
||||
path: .minio/certs/CAs/public.crt
|
||||
path: CAs/public.crt
|
||||
```
|
||||
|
||||
Note that the `secretName` should be same as the secret name created in previous step. Then add the below section under
|
||||
@@ -71,10 +75,10 @@ Note that the `secretName` should be same as the secret name created in previous
|
||||
```yaml
|
||||
volumeMounts:
|
||||
- name: secret-volume
|
||||
mountPath: /<user-running-minio>/
|
||||
mountPath: /<user-running-minio>/.minio/certs
|
||||
```
|
||||
|
||||
Here the name of `volumeMount` should match the name of `volume` created previously. Also `mountPath` is the path of
|
||||
Minio server's config directory, (used to store the certificates). By default the location is
|
||||
`/user-running-minio/.minio/certs`. Update the `mountPath` to appropriate parent directory for Minio server config
|
||||
directory. (Tip: In default Kubernetes configuration this will be `/root`).
|
||||
Here the name of `volumeMount` should match the name of `volume` created previously. Also `mountPath` must be set to the path of
|
||||
the Minio server's config sub-directory that is used to store certificates. By default, the location is
|
||||
`/user-running-minio/.minio/certs`. Tip: In a standard Kubernetes configuration, this will be `/root/.minio/certs`.
|
||||
Kubernetes will mount the secrets volume read-only, so avoid setting `mountPath` to a path that Minio server expects to write to.
|
||||
|
||||
@@ -28,4 +28,7 @@ type Info struct {
|
||||
Files uint64
|
||||
Ffree uint64
|
||||
FSType string
|
||||
|
||||
// Usage is calculated per tenant.
|
||||
Usage uint64
|
||||
}
|
||||
|
||||
+4
-2
@@ -61,11 +61,13 @@ func NewReader(src io.Reader, size int64, md5Hex, sha256Hex string) (*Reader, er
|
||||
if len(sha256sum) != 0 {
|
||||
sha256Hash = sha256.New()
|
||||
}
|
||||
|
||||
if size >= 0 {
|
||||
src = io.LimitReader(src, size)
|
||||
}
|
||||
return &Reader{
|
||||
md5sum: md5sum,
|
||||
sha256sum: sha256sum,
|
||||
src: io.LimitReader(src, size),
|
||||
src: src,
|
||||
size: size,
|
||||
md5Hash: md5.New(),
|
||||
sha256Hash: sha256Hash,
|
||||
|
||||
@@ -5,7 +5,7 @@ This quickstart guide will show you how to install the Minio Admin client SDK, c
|
||||
|
||||
This document assumes that you have a working [Golang setup](https://docs.minio.io/docs/how-to-install-golang).
|
||||
|
||||
## Download from Github
|
||||
## Download from GitHub
|
||||
|
||||
```sh
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2018 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
|
||||
// dummy values, please replace them with original values.
|
||||
|
||||
// API requests are secure (HTTPS) if secure=true and insecure (HTTPS) otherwise.
|
||||
// New returns an Minio Admin client object.
|
||||
madmClnt, err := madmin.New("your-minio.example.com:9000", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY", true)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
st, err := madmClnt.ServerInfo()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Println(st)
|
||||
}
|
||||
@@ -44,10 +44,8 @@ type DriveInfo HealDriveInfo
|
||||
|
||||
// StorageInfo - represents total capacity of underlying storage.
|
||||
type StorageInfo struct {
|
||||
// Total disk space.
|
||||
Total int64
|
||||
// Free available disk space.
|
||||
Free int64
|
||||
Used uint64 // Total used spaced per tenant.
|
||||
|
||||
// Backend type.
|
||||
Backend struct {
|
||||
// Represents various backend types, currently on FS and Erasure.
|
||||
|
||||
+12
-12
@@ -29,26 +29,26 @@ const ResourceARNPrefix = "arn:aws:s3:::"
|
||||
|
||||
// Resource - resource in policy statement.
|
||||
type Resource struct {
|
||||
bucketName string
|
||||
pattern string
|
||||
BucketName string
|
||||
Pattern string
|
||||
}
|
||||
|
||||
func (r Resource) isBucketPattern() bool {
|
||||
return !strings.Contains(r.pattern, "/")
|
||||
return !strings.Contains(r.Pattern, "/")
|
||||
}
|
||||
|
||||
func (r Resource) isObjectPattern() bool {
|
||||
return strings.Contains(r.pattern, "/") || strings.Contains(r.bucketName, "*")
|
||||
return strings.Contains(r.Pattern, "/") || strings.Contains(r.BucketName, "*")
|
||||
}
|
||||
|
||||
// IsValid - checks whether Resource is valid or not.
|
||||
func (r Resource) IsValid() bool {
|
||||
return r.bucketName != "" && r.pattern != ""
|
||||
return r.BucketName != "" && r.Pattern != ""
|
||||
}
|
||||
|
||||
// Match - matches object name with resource pattern.
|
||||
func (r Resource) Match(resource string) bool {
|
||||
return wildcard.Match(r.pattern, resource)
|
||||
return wildcard.Match(r.Pattern, resource)
|
||||
}
|
||||
|
||||
// MarshalJSON - encodes Resource to JSON data.
|
||||
@@ -61,7 +61,7 @@ func (r Resource) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (r Resource) String() string {
|
||||
return ResourceARNPrefix + r.pattern
|
||||
return ResourceARNPrefix + r.Pattern
|
||||
}
|
||||
|
||||
// UnmarshalJSON - decodes JSON data to Resource.
|
||||
@@ -87,7 +87,7 @@ func (r Resource) Validate(bucketName string) error {
|
||||
return fmt.Errorf("invalid resource")
|
||||
}
|
||||
|
||||
if !wildcard.Match(r.bucketName, bucketName) {
|
||||
if !wildcard.Match(r.BucketName, bucketName) {
|
||||
return fmt.Errorf("bucket name does not match")
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ func parseResource(s string) (Resource, error) {
|
||||
}
|
||||
|
||||
return Resource{
|
||||
bucketName: bucketName,
|
||||
pattern: pattern,
|
||||
BucketName: bucketName,
|
||||
Pattern: pattern,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ func NewResource(bucketName, keyName string) Resource {
|
||||
}
|
||||
|
||||
return Resource{
|
||||
bucketName: bucketName,
|
||||
pattern: pattern,
|
||||
BucketName: bucketName,
|
||||
Pattern: pattern,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user