mirror of
https://github.com/pgsty/minio.git
synced 2026-11-02 13:52:08 +03:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 85a57d2021 | |||
| d67e423a32 | |||
| e76fe435c4 | |||
| 1a71004c91 | |||
| 1e50951a4a | |||
| 2c5f2e9669 | |||
| b052bfa79e | |||
| 8eb838bf91 | |||
| 98315b8e60 | |||
| b87cc3d643 | |||
| 4d02f9bccf | |||
| cf8d12d169 |
@@ -101,7 +101,7 @@ iptables -A INPUT -p tcp --dport 9000:9010 -j ACCEPT
|
||||
service iptables restart
|
||||
```
|
||||
|
||||
### ufw in Debian
|
||||
### ufw
|
||||
|
||||
For hosts with ufw enabled (Debian based distros), you can use `ufw` command to allow traffic to specific ports. Use below command to allow access to port 9000
|
||||
|
||||
@@ -115,6 +115,26 @@ Below command enables all incoming traffic to ports ranging from 9000 to 9010.
|
||||
ufw allow 9000:9010/tcp
|
||||
```
|
||||
|
||||
### firewall-cmd
|
||||
|
||||
For hosts with firewall-cmd enabled (CentOS), you can use `firewall-cmd` command to allow traffic to specific ports. Use below commands to allow access to port 9000
|
||||
|
||||
```sh
|
||||
firewall-cmd --get-active-zones
|
||||
```
|
||||
|
||||
This command gets the active zone(s). Now, apply port rules to the relevant zones returned above. For example if the zone is `public`, use
|
||||
|
||||
```sh
|
||||
firewall-cmd --zone=public --add-port=9000/tcp --permanent
|
||||
```
|
||||
|
||||
Note that `permanent` makes sure the rules are persistent across firewall start, restart or reload. Finally reload the firewall for changes to take effect.
|
||||
|
||||
```sh
|
||||
firewall-cmd --reload
|
||||
```
|
||||
|
||||
## Test using Minio Browser
|
||||
Minio Server comes with an embedded web based object browser. Point your web browser to http://127.0.0.1:9000 ensure your server has started successfully.
|
||||
|
||||
|
||||
@@ -33,7 +33,11 @@ export const MainActions = ({
|
||||
)
|
||||
const onFileUpload = e => {
|
||||
e.preventDefault()
|
||||
uploadFile(e.target.files[0])
|
||||
let files = e.target.files
|
||||
let filesToUploadCount = files.length
|
||||
for (let i = 0; i < filesToUploadCount; i++) {
|
||||
uploadFile(files.item(i))
|
||||
}
|
||||
e.target.value = null
|
||||
}
|
||||
|
||||
@@ -55,6 +59,7 @@ export const MainActions = ({
|
||||
onChange={onFileUpload}
|
||||
style={{ display: "none" }}
|
||||
id="file-input"
|
||||
multiple={true}
|
||||
/>
|
||||
<label htmlFor="file-input">
|
||||
{" "}
|
||||
|
||||
@@ -63,11 +63,20 @@ describe("MainActions", () => {
|
||||
it("should call uploadFile when a file is selected for upload", () => {
|
||||
const uploadFile = jest.fn()
|
||||
const wrapper = shallow(<MainActions uploadFile={uploadFile} />)
|
||||
const file = new Blob(["file content"], { type: "text/plain" })
|
||||
wrapper.find("#file-input").simulate("change", {
|
||||
const files = [new Blob(["file content"], { type: "text/plain" })]
|
||||
const input = wrapper.find("#file-input")
|
||||
const event = {
|
||||
preventDefault: jest.fn(),
|
||||
target: { files: [file] }
|
||||
})
|
||||
expect(uploadFile).toHaveBeenCalledWith(file)
|
||||
target: {
|
||||
files: {
|
||||
length: files.length,
|
||||
item: function(index) {
|
||||
return files[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
input.simulate("change", event)
|
||||
expect(uploadFile).toHaveBeenCalledWith(files[0])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package cmd
|
||||
|
||||
import "go/build"
|
||||
|
||||
// DO NOT EDIT THIS FILE DIRECTLY. These are build-time constants
|
||||
// set through ‘buildscripts/gen-ldflags.go’.
|
||||
var (
|
||||
// GOPATH - GOPATH value at the time of build.
|
||||
GOPATH = build.Default.GOPATH
|
||||
GOPATH = ""
|
||||
|
||||
// Go get development tag.
|
||||
goGetTag = "DEVELOPMENT.GOGET"
|
||||
|
||||
+25
-69
@@ -315,27 +315,18 @@ func shouldInitXLDisks(errs []error) bool {
|
||||
}
|
||||
|
||||
// loadFormatXLAll - load all format config from all input disks in parallel.
|
||||
func loadFormatXLAll(endpoints EndpointList) ([]*formatXLV3, []error) {
|
||||
func loadFormatXLAll(storageDisks []StorageAPI) ([]*formatXLV3, []error) {
|
||||
// Initialize sync waitgroup.
|
||||
var wg = &sync.WaitGroup{}
|
||||
|
||||
bootstrapDisks := make([]StorageAPI, len(endpoints))
|
||||
for i, endpoint := range endpoints {
|
||||
disk, err := newStorageAPI(endpoint)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
bootstrapDisks[i] = disk
|
||||
}
|
||||
|
||||
// Initialize list of errors.
|
||||
var sErrs = make([]error, len(bootstrapDisks))
|
||||
var sErrs = make([]error, len(storageDisks))
|
||||
|
||||
// Initialize format configs.
|
||||
var formats = make([]*formatXLV3, len(bootstrapDisks))
|
||||
var formats = make([]*formatXLV3, len(storageDisks))
|
||||
|
||||
// Load format from each disk in parallel
|
||||
for index, disk := range bootstrapDisks {
|
||||
for index, disk := range storageDisks {
|
||||
if disk == nil {
|
||||
sErrs[index] = errDiskNotFound
|
||||
continue
|
||||
@@ -344,10 +335,9 @@ func loadFormatXLAll(endpoints EndpointList) ([]*formatXLV3, []error) {
|
||||
// Launch go-routine per disk.
|
||||
go func(index int, disk StorageAPI) {
|
||||
defer wg.Done()
|
||||
|
||||
format, lErr := loadFormatXL(disk)
|
||||
if lErr != nil {
|
||||
// close the internal connection, to avoid fd leaks.
|
||||
disk.Close()
|
||||
sErrs[index] = lErr
|
||||
return
|
||||
}
|
||||
@@ -362,26 +352,6 @@ func loadFormatXLAll(endpoints EndpointList) ([]*formatXLV3, []error) {
|
||||
return formats, sErrs
|
||||
}
|
||||
|
||||
func undoSaveFormatXLAll(disks []StorageAPI) {
|
||||
// Initialize sync waitgroup.
|
||||
var wg = &sync.WaitGroup{}
|
||||
// Undo previous save format.json entry from all underlying storage disks.
|
||||
for index, disk := range disks {
|
||||
if disk == nil {
|
||||
continue
|
||||
}
|
||||
wg.Add(1)
|
||||
// Delete a bucket inside a go-routine.
|
||||
go func(index int, disk StorageAPI) {
|
||||
defer wg.Done()
|
||||
_ = disk.DeleteFile(minioMetaBucket, formatConfigFile)
|
||||
}(index, disk)
|
||||
}
|
||||
|
||||
// Wait for all make vol to finish.
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func saveFormatXL(disk StorageAPI, format interface{}) error {
|
||||
// Marshal and write to disk.
|
||||
formatBytes, err := json.Marshal(format)
|
||||
@@ -390,7 +360,7 @@ func saveFormatXL(disk StorageAPI, format interface{}) error {
|
||||
}
|
||||
|
||||
// Purge any existing temporary file, okay to ignore errors here.
|
||||
disk.DeleteFile(minioMetaBucket, formatConfigFileTmp)
|
||||
defer disk.DeleteFile(minioMetaBucket, formatConfigFileTmp)
|
||||
|
||||
// Append file `format.json.tmp`.
|
||||
if err = disk.AppendFile(minioMetaBucket, formatConfigFileTmp, formatBytes); err != nil {
|
||||
@@ -550,12 +520,7 @@ func formatXLV3Check(reference *formatXLV3, format *formatXLV3) error {
|
||||
}
|
||||
|
||||
// saveFormatXLAll - populates `format.json` on disks in its order.
|
||||
func saveFormatXLAll(endpoints EndpointList, formats []*formatXLV3) error {
|
||||
storageDisks, err := initStorageDisks(endpoints)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func saveFormatXLAll(storageDisks []StorageAPI, formats []*formatXLV3) error {
|
||||
var errs = make([]error, len(storageDisks))
|
||||
|
||||
var wg = &sync.WaitGroup{}
|
||||
@@ -576,15 +541,18 @@ func saveFormatXLAll(endpoints EndpointList, formats []*formatXLV3) error {
|
||||
// Wait for the routines to finish.
|
||||
wg.Wait()
|
||||
|
||||
writeQuorum := len(endpoints)/2 + 1
|
||||
err = reduceWriteQuorumErrs(errs, nil, writeQuorum)
|
||||
if errors.Cause(err) == errXLWriteQuorum {
|
||||
// Purge all successfully created `format.json`
|
||||
// when we do not have enough quorum.
|
||||
undoSaveFormatXLAll(storageDisks)
|
||||
}
|
||||
writeQuorum := len(storageDisks)/2 + 1
|
||||
return reduceWriteQuorumErrs(errs, nil, writeQuorum)
|
||||
}
|
||||
|
||||
return err
|
||||
// relinquishes the underlying connection for all storage disks.
|
||||
func closeStorageDisks(storageDisks []StorageAPI) {
|
||||
for _, disk := range storageDisks {
|
||||
if disk == nil {
|
||||
continue
|
||||
}
|
||||
disk.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize storage disks based on input arguments.
|
||||
@@ -592,8 +560,6 @@ func initStorageDisks(endpoints EndpointList) ([]StorageAPI, error) {
|
||||
// Bootstrap disks.
|
||||
storageDisks := make([]StorageAPI, len(endpoints))
|
||||
for index, endpoint := range endpoints {
|
||||
// Intentionally ignore disk not found errors. XL is designed
|
||||
// to handle these errors internally.
|
||||
storage, err := newStorageAPI(endpoint)
|
||||
if err != nil && err != errDiskNotFound {
|
||||
return nil, err
|
||||
@@ -625,12 +591,7 @@ func formatXLV3ThisEmpty(formats []*formatXLV3) bool {
|
||||
}
|
||||
|
||||
// fixFormatXLV3 - fix format XL configuration on all disks.
|
||||
func fixFormatXLV3(endpoints EndpointList, formats []*formatXLV3) error {
|
||||
storageDisks, err := initStorageDisks(endpoints)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func fixFormatXLV3(storageDisks []StorageAPI, endpoints EndpointList, formats []*formatXLV3) error {
|
||||
for i, format := range formats {
|
||||
if format == nil || !endpoints[i].IsLocal {
|
||||
continue
|
||||
@@ -644,7 +605,7 @@ func fixFormatXLV3(endpoints EndpointList, formats []*formatXLV3) error {
|
||||
}
|
||||
if format.XL.This == "" {
|
||||
formats[i].XL.This = format.XL.Sets[0][i]
|
||||
if err = saveFormatXL(storageDisks[i], formats[i]); err != nil {
|
||||
if err := saveFormatXL(storageDisks[i], formats[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -653,9 +614,9 @@ func fixFormatXLV3(endpoints EndpointList, formats []*formatXLV3) error {
|
||||
}
|
||||
|
||||
// initFormatXL - save XL format configuration on all disks.
|
||||
func initFormatXL(endpoints EndpointList, setCount, disksPerSet int) (format *formatXLV3, err error) {
|
||||
func initFormatXL(storageDisks []StorageAPI, setCount, disksPerSet int) (format *formatXLV3, err error) {
|
||||
format = newFormatXLV3(setCount, disksPerSet)
|
||||
formats := make([]*formatXLV3, len(endpoints))
|
||||
formats := make([]*formatXLV3, len(storageDisks))
|
||||
|
||||
for i := 0; i < setCount; i++ {
|
||||
for j := 0; j < disksPerSet; j++ {
|
||||
@@ -666,12 +627,12 @@ func initFormatXL(endpoints EndpointList, setCount, disksPerSet int) (format *fo
|
||||
}
|
||||
|
||||
// Initialize meta volume, if volume already exists ignores it.
|
||||
if err = initFormatXLMetaVolume(endpoints, formats); err != nil {
|
||||
if err = initFormatXLMetaVolume(storageDisks, formats); err != nil {
|
||||
return format, fmt.Errorf("Unable to initialize '.minio.sys' meta volume, %s", err)
|
||||
}
|
||||
|
||||
// Save formats `format.json` across all disks.
|
||||
if err = saveFormatXLAll(endpoints, formats); err != nil {
|
||||
if err = saveFormatXLAll(storageDisks, formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -702,12 +663,7 @@ func makeFormatXLMetaVolumes(disk StorageAPI) error {
|
||||
var initMetaVolIgnoredErrs = append(baseIgnoredErrs, errVolumeExists)
|
||||
|
||||
// Initializes meta volume on all input storage disks.
|
||||
func initFormatXLMetaVolume(endpoints EndpointList, formats []*formatXLV3) error {
|
||||
storageDisks, err := initStorageDisks(endpoints)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func initFormatXLMetaVolume(storageDisks []StorageAPI, formats []*formatXLV3) error {
|
||||
// This happens for the first time, but keep this here since this
|
||||
// is the only place where it can be made expensive optimizing all
|
||||
// other calls. Create minio meta volume, if it doesn't exist yet.
|
||||
|
||||
@@ -87,6 +87,11 @@ func TestFixFormatV3(t *testing.T) {
|
||||
}
|
||||
endpoints := mustGetNewEndpointList(xlDirs...)
|
||||
|
||||
storageDisks, err := initStorageDisks(endpoints)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
format := newFormatXLV3(1, 8)
|
||||
formats := make([]*formatXLV3, 8)
|
||||
|
||||
@@ -96,17 +101,18 @@ func TestFixFormatV3(t *testing.T) {
|
||||
formats[j] = &newFormat
|
||||
}
|
||||
|
||||
if err = initFormatXLMetaVolume(endpoints, formats); err != nil {
|
||||
if err = initFormatXLMetaVolume(storageDisks, formats); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
formats[1] = nil
|
||||
expThis := formats[2].XL.This
|
||||
formats[2].XL.This = ""
|
||||
if err := fixFormatXLV3(endpoints, formats); err != nil {
|
||||
if err := fixFormatXLV3(storageDisks, endpoints, formats); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
newFormats, errs := loadFormatXLAll(endpoints)
|
||||
|
||||
newFormats, errs := loadFormatXLAll(storageDisks)
|
||||
for _, err := range errs {
|
||||
if err != nil && errors.Cause(err) != errUnformattedDisk {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -73,7 +73,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -97,7 +97,7 @@ EXAMPLES:
|
||||
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="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
|
||||
@@ -64,7 +64,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -83,7 +83,7 @@ EXAMPLES:
|
||||
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="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
|
||||
@@ -110,7 +110,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -135,7 +135,7 @@ EXAMPLES:
|
||||
$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
|
||||
$ export MINIO_ACCESS_KEY=accesskey
|
||||
$ export MINIO_SECRET_KEY=secretkey
|
||||
$ export MINIO_CACHE_DRIVES="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ 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
|
||||
|
||||
@@ -75,7 +75,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -99,7 +99,7 @@ EXAMPLES:
|
||||
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="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
|
||||
@@ -51,7 +51,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -70,7 +70,7 @@ EXAMPLES:
|
||||
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="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ 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
|
||||
|
||||
@@ -72,7 +72,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_DOMAIN: To enable virtual-host-style requests, set this value to Minio host domain name.
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -90,7 +90,7 @@ EXAMPLES:
|
||||
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="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
|
||||
@@ -57,7 +57,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -81,7 +81,7 @@ EXAMPLES:
|
||||
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="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
|
||||
@@ -74,7 +74,7 @@ ENVIRONMENT VARIABLES: (Default values in parenthesis)
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -92,7 +92,7 @@ EXAMPLES:
|
||||
$ {{.HelpName}}
|
||||
|
||||
2. Start minio gateway server for Sia backend with edge caching enabled.
|
||||
$ export MINIO_CACHE_DRIVES="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}}
|
||||
|
||||
+12
-3
@@ -375,9 +375,18 @@ var defaultAllowableHTTPMethods = []string{
|
||||
|
||||
// setCorsHandler handler for CORS (Cross Origin Resource Sharing)
|
||||
func setCorsHandler(h http.Handler) http.Handler {
|
||||
commonS3Headers := []string{"Content-Length", "Content-Type", "Connection",
|
||||
"Date", "ETag", "Server", "x-amz-delete-marker", "x-amz-id-2",
|
||||
"x-amz-request-id", "x-amz-version-id"}
|
||||
commonS3Headers := []string{
|
||||
"Date",
|
||||
"ETag",
|
||||
"Server",
|
||||
"Connection",
|
||||
"Accept-Ranges",
|
||||
"Content-Range",
|
||||
"Content-Encoding",
|
||||
"Content-Length",
|
||||
"Content-Type",
|
||||
"x-amz-request-id",
|
||||
}
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
AllowedMethods: defaultAllowableHTTPMethods,
|
||||
|
||||
@@ -19,6 +19,7 @@ package cmd
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -98,13 +99,17 @@ func (log *Logger) Printf(format string, args ...interface{}) {
|
||||
|
||||
func init() {
|
||||
var goPathList []string
|
||||
var defaultgoPathList []string
|
||||
// Add all possible GOPATH paths into trimStrings
|
||||
// Split GOPATH depending on the OS type
|
||||
if runtime.GOOS == "windows" {
|
||||
goPathList = strings.Split(GOPATH, ";")
|
||||
defaultgoPathList = strings.Split(build.Default.GOPATH, ";")
|
||||
} else {
|
||||
// All other types of OSs
|
||||
goPathList = strings.Split(GOPATH, ":")
|
||||
defaultgoPathList = strings.Split(build.Default.GOPATH, ":")
|
||||
|
||||
}
|
||||
|
||||
// Add trim string "{GOROOT}/src/" into trimStrings
|
||||
@@ -115,6 +120,11 @@ func init() {
|
||||
for _, goPathString := range goPathList {
|
||||
trimStrings = append(trimStrings, filepath.Join(goPathString, "src")+string(filepath.Separator))
|
||||
}
|
||||
|
||||
for _, defaultgoPathString := range defaultgoPathList {
|
||||
trimStrings = append(trimStrings, filepath.Join(defaultgoPathString, "src")+string(filepath.Separator))
|
||||
}
|
||||
|
||||
// Add "github.com/minio/minio" as the last to cover
|
||||
// paths like "{GOROOT}/src/github.com/minio/minio"
|
||||
// and "{GOPATH}/src/github.com/minio/minio"
|
||||
|
||||
+105
-55
@@ -88,6 +88,95 @@ func formatXLCleanupTmpLocalEndpoints(endpoints EndpointList) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// validate reference format against list of XL formats.
|
||||
func validateXLFormats(format *formatXLV3, formats []*formatXLV3, endpoints EndpointList, setCount, drivesPerSet int) error {
|
||||
for i := range formats {
|
||||
if formats[i] == nil {
|
||||
continue
|
||||
}
|
||||
if err := formatXLV3Check(format, formats[i]); err != nil {
|
||||
return fmt.Errorf("%s format error: %s", endpoints[i], err)
|
||||
}
|
||||
}
|
||||
if len(format.XL.Sets) != setCount {
|
||||
return fmt.Errorf("Current backend format is inconsistent with input args (%s), Expected set count %d, got %d", endpoints, len(format.XL.Sets), setCount)
|
||||
}
|
||||
if len(format.XL.Sets[0]) != drivesPerSet {
|
||||
return fmt.Errorf("Current backend format is inconsistent with input args (%s), Expected drive count per set %d, got %d", endpoints, len(format.XL.Sets[0]), drivesPerSet)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Following error message is added to fix a regression in release
|
||||
// RELEASE.2018-03-16T22-52-12Z after migrating v1 to v2 to v3. This
|
||||
// migration failed to capture '.This' field properly which indicates
|
||||
// the disk UUID association. Below error message is returned when
|
||||
// we see this situation in format.json, for more info refer
|
||||
// https://github.com/minio/minio/issues/5667
|
||||
var errXLV3ThisEmpty = fmt.Errorf("XL format version 3 has This field empty")
|
||||
|
||||
// connect to list of endpoints and load all XL disk formats, validate the formats are correct
|
||||
// and are in quorum, if no formats are found attempt to initialize all of them for the first
|
||||
// time. additionally make sure to close all the disks used in this attempt.
|
||||
func connectLoadInitFormats(firstDisk bool, endpoints EndpointList, setCount, drivesPerSet int) (*formatXLV3, error) {
|
||||
storageDisks, err := initStorageDisks(endpoints)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer closeStorageDisks(storageDisks)
|
||||
|
||||
// Attempt to load all `format.json` from all disks.
|
||||
formatConfigs, sErrs := loadFormatXLAll(storageDisks)
|
||||
|
||||
// Pre-emptively check if one of the formatted disks
|
||||
// is invalid. This function returns success for the
|
||||
// most part unless one of the formats is not consistent
|
||||
// with expected XL format. For example if a user is
|
||||
// trying to pool FS backend into an XL set.
|
||||
if err = checkFormatXLValues(formatConfigs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, sErr := range sErrs {
|
||||
if _, ok := formatCriticalErrors[errors.Cause(sErr)]; ok {
|
||||
return nil, fmt.Errorf("Disk %s: %s", endpoints[i], sErr)
|
||||
}
|
||||
}
|
||||
|
||||
if shouldInitXLDisks(sErrs) {
|
||||
if !firstDisk {
|
||||
return nil, errNotFirstDisk
|
||||
}
|
||||
return initFormatXL(storageDisks, setCount, drivesPerSet)
|
||||
}
|
||||
|
||||
// Following function is added to fix a regressions which was introduced
|
||||
// in release RELEASE.2018-03-16T22-52-12Z after migrating v1 to v2 to v3.
|
||||
// This migration failed to capture '.This' field properly which indicates
|
||||
// the disk UUID association. Below function is called to handle and fix
|
||||
// this regression, for more info refer https://github.com/minio/minio/issues/5667
|
||||
if err = fixFormatXLV3(storageDisks, endpoints, formatConfigs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If any of the .This field is still empty, we return error.
|
||||
if formatXLV3ThisEmpty(formatConfigs) {
|
||||
return nil, errXLV3ThisEmpty
|
||||
}
|
||||
|
||||
format, err := getFormatXLInQuorum(formatConfigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Validate all format configs with reference format.
|
||||
if err = validateXLFormats(format, formatConfigs, endpoints, setCount, drivesPerSet); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return format, nil
|
||||
}
|
||||
|
||||
// Format disks before initialization of object layer.
|
||||
func waitForFormatXL(firstDisk bool, endpoints EndpointList, setCount, disksPerSet int) (format *formatXLV3, err error) {
|
||||
if len(endpoints) == 0 || setCount == 0 || disksPerSet == 0 {
|
||||
@@ -121,65 +210,26 @@ func waitForFormatXL(firstDisk bool, endpoints EndpointList, setCount, disksPerS
|
||||
for {
|
||||
select {
|
||||
case _ = <-retryTimerCh:
|
||||
// Attempt to load all `format.json` from all disks.
|
||||
formatConfigs, sErrs := loadFormatXLAll(endpoints)
|
||||
|
||||
// Pre-emptively check if one of the formatted disks
|
||||
// is invalid. This function returns success for the
|
||||
// most part unless one of the formats is not consistent
|
||||
// with expected XL format. For example if a user is
|
||||
// trying to pool FS backend into an XL set.
|
||||
if err = checkFormatXLValues(formatConfigs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, sErr := range sErrs {
|
||||
if _, ok := formatCriticalErrors[errors.Cause(sErr)]; ok {
|
||||
return nil, fmt.Errorf("Disk %s: %s", endpoints[i], sErr)
|
||||
}
|
||||
}
|
||||
|
||||
if shouldInitXLDisks(sErrs) {
|
||||
if !firstDisk {
|
||||
format, err := connectLoadInitFormats(firstDisk, endpoints, setCount, disksPerSet)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case errNotFirstDisk:
|
||||
// Fresh setup, wait for first server to be up.
|
||||
console.Println("Waiting for the first server to format the disks.")
|
||||
continue
|
||||
case errXLReadQuorum:
|
||||
// no quorum available continue to wait for minimum number of servers.
|
||||
console.Printf("Waiting for a minimum of %d disks to come online (elapsed %s)\n", len(endpoints)/2, getElapsedTime())
|
||||
continue
|
||||
case errXLV3ThisEmpty:
|
||||
// need to wait for this error to be healed, so continue.
|
||||
continue
|
||||
default:
|
||||
// For all other unhandled errors we exit and fail.
|
||||
return nil, err
|
||||
}
|
||||
return initFormatXL(endpoints, setCount, disksPerSet)
|
||||
}
|
||||
|
||||
// Following function is added to fix a regressions which was introduced
|
||||
// in release RELEASE.2018-03-16T22-52-12Z after migrating v1 to v2 to v3.
|
||||
// This migration failed to capture '.This' field properly which indicates
|
||||
// the disk UUID association. Below function is called to handle and fix
|
||||
// this regression, for more info refer https://github.com/minio/minio/issues/5667
|
||||
if err = fixFormatXLV3(endpoints, formatConfigs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If any of the .This field is still empty we wait them to be fixed.
|
||||
if formatXLV3ThisEmpty(formatConfigs) {
|
||||
continue
|
||||
}
|
||||
|
||||
format, err = getFormatXLInQuorum(formatConfigs)
|
||||
if err == nil {
|
||||
for i := range formatConfigs {
|
||||
if formatConfigs[i] == nil {
|
||||
continue
|
||||
}
|
||||
if err = formatXLV3Check(format, formatConfigs[i]); err != nil {
|
||||
return nil, fmt.Errorf("%s format error: %s", endpoints[i], err)
|
||||
}
|
||||
}
|
||||
if len(format.XL.Sets) != globalXLSetCount {
|
||||
return nil, fmt.Errorf("Current backend format is inconsistent with input args (%s), Expected set count %d, got %d", endpoints, len(format.XL.Sets), globalXLSetCount)
|
||||
}
|
||||
if len(format.XL.Sets[0]) != globalXLSetDriveCount {
|
||||
return nil, fmt.Errorf("Current backend format is inconsistent with input args (%s), Expected drive count per set %d, got %d", endpoints, len(format.XL.Sets[0]), globalXLSetDriveCount)
|
||||
}
|
||||
return format, nil
|
||||
}
|
||||
console.Printf("Waiting for a minimum of %d disks to come online (elapsed %s)\n", len(endpoints)/2, getElapsedTime())
|
||||
return format, nil
|
||||
case <-globalOSSignalCh:
|
||||
return nil, fmt.Errorf("Initializing data volumes gracefully stopped")
|
||||
}
|
||||
|
||||
+2
-2
@@ -68,7 +68,7 @@ ENVIRONMENT VARIABLES:
|
||||
MINIO_BROWSER: To disable web browser access, set this value to "off".
|
||||
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";".
|
||||
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.
|
||||
|
||||
@@ -115,7 +115,7 @@ EXAMPLES:
|
||||
$ {{.HelpName}} http://node{1...8}.example.com/mnt/export/{1...8}
|
||||
|
||||
7. Start minio server with edge caching enabled.
|
||||
$ export MINIO_CACHE_DRIVES="/home/drive1;/home/drive2;/home/drive3;/home/drive4"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3;/mnt/drive4"
|
||||
$ export MINIO_CACHE_EXCLUDE="bucket1/*;*.png"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ {{.HelpName}} /home/shared
|
||||
|
||||
@@ -58,3 +58,7 @@ var errInvalidRange = errors.New("Invalid range")
|
||||
// errInvalidRangeSource - returned when given range value exceeds
|
||||
// the source object size.
|
||||
var errInvalidRangeSource = errors.New("Range specified exceeds source object size")
|
||||
|
||||
// error returned by disks which are to be initialized are waiting for the
|
||||
// first server to initialize them in distributed set to initialize them.
|
||||
var errNotFirstDisk = errors.New("Not first disk")
|
||||
|
||||
+51
-56
@@ -101,7 +101,7 @@ func connectEndpoint(endpoint Endpoint) (StorageAPI, *formatXLV3, error) {
|
||||
|
||||
format, err := loadFormatXL(disk)
|
||||
if err != nil {
|
||||
// close the internal connection, to avoid fd leaks.
|
||||
// Close the internal connection to avoid connection leaks.
|
||||
disk.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -147,6 +147,8 @@ func (s *xlSets) connectDisks() {
|
||||
i, j, err := findDiskIndex(s.format, format)
|
||||
s.formatMu.RUnlock()
|
||||
if err != nil {
|
||||
// Close the internal connection to avoid connection leaks.
|
||||
disk.Close()
|
||||
printEndpointError(endpoint, err)
|
||||
continue
|
||||
}
|
||||
@@ -215,19 +217,8 @@ func newXLSets(endpoints EndpointList, format *formatXLV3, setCount int, drivesP
|
||||
go s.sets[i].cleanupStaleMultipartUploads(globalMultipartCleanupInterval, globalMultipartExpiry, globalServiceDoneCh)
|
||||
}
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
disk, nformat, err := connectEndpoint(endpoint)
|
||||
if err != nil {
|
||||
errorIf(err, "Unable to connect to endpoint %s", endpoint)
|
||||
continue
|
||||
}
|
||||
i, j, err := findDiskIndex(format, nformat)
|
||||
if err != nil {
|
||||
errorIf(err, "Unable to find the endpoint %s in reference format", endpoint)
|
||||
continue
|
||||
}
|
||||
s.xlDisks[i][j] = disk
|
||||
}
|
||||
// Connect disks right away.
|
||||
s.connectDisks()
|
||||
|
||||
// Initialize and load bucket policies.
|
||||
var err error
|
||||
@@ -267,7 +258,19 @@ func (s *xlSets) StorageInfo(ctx context.Context) StorageInfo {
|
||||
storageInfo.Backend.RRSCData = rrSCData
|
||||
storageInfo.Backend.RRSCParity = rrSCparity
|
||||
|
||||
formats, sErrs := loadFormatXLAll(s.endpoints)
|
||||
storageInfo.Backend.Sets = make([][]madmin.DriveInfo, s.setCount)
|
||||
for i := range storageInfo.Backend.Sets {
|
||||
storageInfo.Backend.Sets[i] = make([]madmin.DriveInfo, s.drivesPerSet)
|
||||
}
|
||||
|
||||
storageDisks, err := initStorageDisks(s.endpoints)
|
||||
if err != nil {
|
||||
return storageInfo
|
||||
}
|
||||
defer closeStorageDisks(storageDisks)
|
||||
|
||||
formats, sErrs := loadFormatXLAll(storageDisks)
|
||||
|
||||
drivesInfo := formatsToDrivesInfo(s.endpoints, formats, sErrs)
|
||||
refFormat, err := getFormatXLInQuorum(formats)
|
||||
if err != nil {
|
||||
@@ -276,11 +279,6 @@ func (s *xlSets) StorageInfo(ctx context.Context) StorageInfo {
|
||||
return storageInfo
|
||||
}
|
||||
|
||||
storageInfo.Backend.Sets = make([][]madmin.DriveInfo, s.setCount)
|
||||
for i := range storageInfo.Backend.Sets {
|
||||
storageInfo.Backend.Sets[i] = make([]madmin.DriveInfo, s.drivesPerSet)
|
||||
}
|
||||
|
||||
// fill all the available/online endpoints
|
||||
for _, drive := range drivesInfo {
|
||||
if drive.UUID == "" {
|
||||
@@ -725,27 +723,22 @@ func (s *xlSets) ListObjects(ctx context.Context, bucket, prefix, marker, delimi
|
||||
return result, toObjectErr(walkResult.err, bucket, prefix)
|
||||
}
|
||||
|
||||
entry := walkResult.entry
|
||||
var objInfo ObjectInfo
|
||||
if hasSuffix(entry, slashSeparator) {
|
||||
// Object name needs to be full path.
|
||||
objInfo.Bucket = bucket
|
||||
objInfo.Name = entry
|
||||
objInfo.IsDir = true
|
||||
var err error
|
||||
if hasSuffix(walkResult.entry, slashSeparator) {
|
||||
objInfo, err = s.getHashedSet(walkResult.entry).getObjectInfoDir(bucket, walkResult.entry)
|
||||
} else {
|
||||
// Set the Mode to a "regular" file.
|
||||
var err error
|
||||
objInfo, err = s.getHashedSet(entry).getObjectInfo(bucket, entry)
|
||||
if err != nil {
|
||||
// Ignore errFileNotFound as the object might have got
|
||||
// deleted in the interim period of listing and getObjectInfo(),
|
||||
// ignore quorum error as it might be an entry from an outdated disk.
|
||||
switch errors.Cause(err) {
|
||||
case errFileNotFound, errXLReadQuorum:
|
||||
continue
|
||||
}
|
||||
return result, toObjectErr(err, bucket, prefix)
|
||||
objInfo, err = s.getHashedSet(walkResult.entry).getObjectInfo(bucket, walkResult.entry)
|
||||
}
|
||||
if err != nil {
|
||||
// Ignore errFileNotFound as the object might have got
|
||||
// deleted in the interim period of listing and getObjectInfo(),
|
||||
// ignore quorum error as it might be an entry from an outdated disk.
|
||||
switch errors.Cause(err) {
|
||||
case errFileNotFound, errXLReadQuorum:
|
||||
continue
|
||||
}
|
||||
return result, toObjectErr(err, bucket, prefix)
|
||||
}
|
||||
nextMarker = objInfo.Name
|
||||
objInfos = append(objInfos, objInfo)
|
||||
@@ -926,8 +919,14 @@ func (s *xlSets) HealFormat(ctx context.Context, dryRun bool) (madmin.HealResult
|
||||
}
|
||||
defer formatLock.Unlock()
|
||||
|
||||
formats, sErrs := loadFormatXLAll(s.endpoints)
|
||||
if err := checkFormatXLValues(formats); err != nil {
|
||||
storageDisks, err := initStorageDisks(s.endpoints)
|
||||
if err != nil {
|
||||
return madmin.HealResultItem{}, err
|
||||
}
|
||||
defer closeStorageDisks(storageDisks)
|
||||
|
||||
formats, sErrs := loadFormatXLAll(storageDisks)
|
||||
if err = checkFormatXLValues(formats); err != nil {
|
||||
return madmin.HealResultItem{}, err
|
||||
}
|
||||
|
||||
@@ -1030,12 +1029,12 @@ func (s *xlSets) HealFormat(ctx context.Context, dryRun bool) (madmin.HealResult
|
||||
|
||||
// Initialize meta volume, if volume already exists ignores it, all disks which
|
||||
// are not found are ignored as well.
|
||||
if err = initFormatXLMetaVolume(s.endpoints, tmpNewFormats); err != nil {
|
||||
if err = initFormatXLMetaVolume(storageDisks, tmpNewFormats); err != nil {
|
||||
return madmin.HealResultItem{}, fmt.Errorf("Unable to initialize '.minio.sys' meta volume, %s", err)
|
||||
}
|
||||
|
||||
// Save formats `format.json` across all disks.
|
||||
if err = saveFormatXLAll(s.endpoints, tmpNewFormats); err != nil {
|
||||
if err = saveFormatXLAll(storageDisks, tmpNewFormats); err != nil {
|
||||
return madmin.HealResultItem{}, err
|
||||
}
|
||||
|
||||
@@ -1270,23 +1269,19 @@ func (s *xlSets) listObjectsHeal(bucket, prefix, marker, delimiter string, maxKe
|
||||
if walkResult.err != nil {
|
||||
return loi, toObjectErr(walkResult.err, bucket, prefix)
|
||||
}
|
||||
entry := walkResult.entry
|
||||
var objInfo ObjectInfo
|
||||
if hasSuffix(entry, slashSeparator) {
|
||||
// Object name needs to be full path.
|
||||
objInfo.Bucket = bucket
|
||||
objInfo.Name = entry
|
||||
objInfo.IsDir = true
|
||||
var err error
|
||||
if hasSuffix(walkResult.entry, slashSeparator) {
|
||||
objInfo, err = s.getHashedSet(walkResult.entry).getObjectInfoDir(bucket, walkResult.entry)
|
||||
} else {
|
||||
var err error
|
||||
objInfo, err = s.getHashedSet(entry).getObjectInfo(bucket, entry)
|
||||
if err != nil {
|
||||
// Ignore errFileNotFound
|
||||
if errors.Cause(err) == errFileNotFound {
|
||||
continue
|
||||
}
|
||||
return loi, toObjectErr(err, bucket, prefix)
|
||||
objInfo, err = s.getHashedSet(walkResult.entry).getObjectInfo(bucket, walkResult.entry)
|
||||
}
|
||||
if err != nil {
|
||||
// Ignore errFileNotFound
|
||||
if errors.Cause(err) == errFileNotFound {
|
||||
continue
|
||||
}
|
||||
return loi, toObjectErr(err, bucket, prefix)
|
||||
}
|
||||
nextMarker = objInfo.Name
|
||||
objInfos = append(objInfos, objInfo)
|
||||
|
||||
+1
-8
@@ -59,14 +59,7 @@ var xlTreeWalkIgnoredErrs = append(baseIgnoredErrs, errDiskAccessDenied, errVolu
|
||||
// Shutdown function for object storage interface.
|
||||
func (xl xlObjects) Shutdown(ctx context.Context) error {
|
||||
// Add any object layer shutdown activities here.
|
||||
for _, disk := range xl.getDisks() {
|
||||
// This closes storage rpc client connections if any.
|
||||
// Otherwise this is a no-op.
|
||||
if disk == nil {
|
||||
continue
|
||||
}
|
||||
disk.Close()
|
||||
}
|
||||
closeStorageDisks(xl.getDisks())
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Minio Server `config.json` (v22) Guide [](https://slack.minio.io) [](https://goreportcard.com/report/minio/minio) [](https://hub.docker.com/r/minio/minio/) [](https://codecov.io/gh/minio/minio)
|
||||
# Minio Server `config.json` (v23) Guide [](https://slack.minio.io) [](https://goreportcard.com/report/minio/minio) [](https://hub.docker.com/r/minio/minio/) [](https://codecov.io/gh/minio/minio)
|
||||
|
||||
Minio server stores all its configuration data in `${HOME}/.minio/config.json` file by default. Following sections provide detailed explanation of each fields and how to customize them. A complete example of `config.json` is available [here](https://raw.githubusercontent.com/minio/minio/master/docs/config/config.sample.json)
|
||||
|
||||
@@ -95,7 +95,7 @@ By default, parity for objects with standard storage class is set to `N/2`, and
|
||||
### Cache
|
||||
|Field|Type|Description|
|
||||
|:---|:---|:---|
|
||||
|``drives``| _[]string_ | List of drives|
|
||||
|``drives``| _[]string_ | List of mounted file system drives with [`atime`](http://kerolasa.github.io/filetimes.html) support enabled|
|
||||
|``exclude`` | _[]string_ | List of wildcard patterns for prefixes to exclude from cache |
|
||||
|``expiry`` | _int_ | Days to cache expiry |
|
||||
|
||||
|
||||
@@ -9,16 +9,16 @@ minio server -h
|
||||
...
|
||||
...
|
||||
CACHE:
|
||||
MINIO_CACHE_DRIVES: List of cache drives delimited by ";"
|
||||
MINIO_CACHE_DRIVES: List of mounted cache drives or directories delimited by ";"
|
||||
MINIO_CACHE_EXCLUDE: List of cache exclusion patterns delimited by ";"
|
||||
MINIO_CACHE_EXPIRY: Cache expiry duration in days
|
||||
...
|
||||
...
|
||||
|
||||
7. Start minio server with edge caching enabled on '/drive1', '/drive2' and '/drive3',
|
||||
7. Start minio server with edge caching enabled on '/mnt/drive1', '/mnt/drive2' and '/mnt/drive3',
|
||||
exclude all objects under 'mybucket', exclude all objects with '.pdf' as extension
|
||||
with expiry upto 40 days.
|
||||
$ export MINIO_CACHE_DRIVES="/drive1;/drive2;/drive3"
|
||||
$ export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3"
|
||||
$ export MINIO_CACHE_EXCLUDE="mybucket/*;*.pdf"
|
||||
$ export MINIO_CACHE_EXPIRY=40
|
||||
$ minio server /home/shared
|
||||
@@ -26,7 +26,7 @@ minio server -h
|
||||
|
||||
## Assumptions
|
||||
- Disk cache size defaults to 80% of your drive capacity.
|
||||
- Disk caching requires [`atime`](http://kerolasa.github.io/filetimes.html) support to be enabled on the cache drive.
|
||||
- The cache drives are required to be a filesystem mount point with [`atime`](http://kerolasa.github.io/filetimes.html) support to be enabled on the drive. Alternatively writable directories with atime support can be specified in MINIO_CACHE_DRIVES
|
||||
- Expiration of each cached entry takes user provided expiry as a hint, and defaults to 90 days if not provided.
|
||||
- Garbage collection sweep of the expired cache entries happens whenever cache usage is > 80% of drive capacity, GC continues until sufficient disk space is reclaimed.
|
||||
- An object is only cached when drive has sufficient disk space, upto 100 times the size of the object.
|
||||
@@ -42,6 +42,9 @@ Disk caching caches objects for both **uploaded** and **downloaded** objects i.e
|
||||
|
||||
> NOTE: Expiration happens automatically based on the configured interval as explained above, frequently accessed objects stay alive in cache for a significantly longer time.
|
||||
|
||||
### Crash Recovery
|
||||
Upon restart of minio server after a running minio process is killed or crashes, disk caching resumes automatically. The garbage collection cycle resumes and any previously cached entries are served from cache.
|
||||
|
||||
## Limits
|
||||
- Bucket policies are not cached, so anonymous operations are not supported when backend is offline.
|
||||
- Objects are distributed using deterministic hashing among the list of configured cache drives. If one or more drives go offline, or cache drive configuration is altered in any way, performance may degrade to a linear lookup time depending on the number of disks in cache.
|
||||
|
||||
@@ -11,20 +11,20 @@ Disk caching feature here refers to the use of caching disks to store content cl
|
||||
Install Minio - [Minio Quickstart Guide](https://docs.minio.io/docs/minio).
|
||||
|
||||
### 2. Run Minio with cache
|
||||
Disk caching can be enabled by updating the `cache` config settings for Minio server. Config `cache` settings takes the drive locations, cache expiry duration (in days) and any wildcard patterns to exclude from being cached.
|
||||
Disk caching can be enabled by updating the `cache` config settings for Minio server. Config `cache` settings takes the mounted drive(s) or directory paths, cache expiry duration (in days) and any wildcard patterns to exclude from being cached.
|
||||
|
||||
```json
|
||||
"cache": {
|
||||
"drives": ["/drive1", "/drive2", "/drive3"],
|
||||
"drives": ["/mnt/drive1", "/mnt/drive2", "/mnt/drive3"],
|
||||
"expiry": 90,
|
||||
"exclude": ["*.pdf","mybucket/*"]
|
||||
},
|
||||
```
|
||||
|
||||
The cache settings may also be set through environment variables. When set, environment variables override any `cache` config settings for Minio server. Following example uses `/drive1`, `/drive2` and `/drive3` for caching, with expiry upto 90 days while excluding all objects under bucket `mybucket` and all objects with '.pdf' as extension while starting a standalone erasure coded setup.
|
||||
The cache settings may also be set through environment variables. When set, environment variables override any `cache` config settings for Minio server. Following example uses `/mnt/drive1`, `/mnt/drive2` and `/mnt/drive3` for caching, with expiry upto 90 days while excluding all objects under bucket `mybucket` and all objects with '.pdf' as extension while starting a standalone erasure coded setup.
|
||||
|
||||
```bash
|
||||
export MINIO_CACHE_DRIVES="/drive1;/drive2;/drive3"
|
||||
export MINIO_CACHE_DRIVES="/mnt/drive1;/mnt/drive2;/mnt/drive3"
|
||||
export MINIO_CACHE_EXPIRY=90
|
||||
export MINIO_CACHE_EXCLUDE="*.pdf;mybucket/*"
|
||||
minio server /export{1...24}
|
||||
@@ -34,6 +34,7 @@ minio server /export{1...24}
|
||||
To test this setup, access the Minio server via browser or [`mc`](https://docs.minio.io/docs/minio-client-quickstart-guide). You’ll see the uploaded files are accessible from the all the Minio endpoints.
|
||||
|
||||
# Explore Further
|
||||
- [Disk cache design](https://github.com/minio/minio/blob/master/docs/disk-caching/DESIGN.md)
|
||||
- [Use `mc` with Minio Server](https://docs.minio.io/docs/minio-client-quickstart-guide)
|
||||
- [Use `aws-cli` with Minio Server](https://docs.minio.io/docs/aws-cli-with-minio)
|
||||
- [Use `s3cmd` with Minio Server](https://docs.minio.io/docs/s3cmd-with-minio)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
# Minio Gateway [](https://slack.minio.io)
|
||||
Minio Gateway adds Amazon S3 compatibility to third party cloud storage providers.
|
||||
- [NAS](https://github.com/minio/minio/blob/master/docs/gateway/nas.md)
|
||||
- [Microsoft Azure Blob Storage](https://github.com/minio/minio/blob/master/docs/gateway/azure.md)
|
||||
- [Google Cloud Storage](https://github.com/minio/minio/blob/master/docs/gateway/gcs.md) _Alpha release_
|
||||
- [Backblaze B2](https://github.com/minio/minio/blob/master/docs/gateway/b2.md) _Alpha release_
|
||||
- [Google Cloud Storage](https://github.com/minio/minio/blob/master/docs/gateway/gcs.md)
|
||||
- [Backblaze B2](https://github.com/minio/minio/blob/master/docs/gateway/b2.md)
|
||||
- [Sia Decentralized Cloud Storage](https://github.com/minio/minio/blob/master/docs/gateway/sia.md) _Alpha release_
|
||||
- [Manta Object Storage](https://github.com/minio/minio/blob/master/docs/gateway/triton.md) _Alpha release_
|
||||
|
||||
## Roadmap
|
||||
* Edge Caching - Disk based proxy caching support
|
||||
- [Manta Object Storage](https://github.com/minio/minio/blob/master/docs/gateway/manta.md) _Alpha release_
|
||||
|
||||
|
||||
@@ -51,5 +51,4 @@ Other limitations:
|
||||
## Explore Further
|
||||
- [`mc` command-line interface](https://docs.minio.io/docs/minio-client-quickstart-guide)
|
||||
- [`aws` command-line interface](https://docs.minio.io/docs/aws-cli-with-minio)
|
||||
- [`minfs` filesystem interface](http://docs.minio.io/docs/minfs-quickstart-guide)
|
||||
- [`minio-go` Go SDK](https://docs.minio.io/docs/golang-client-quickstart-guide)
|
||||
|
||||
+10
-3
@@ -2,14 +2,21 @@
|
||||
Minio Gateway adds Amazon S3 compatibility to Backblaze B2 Cloud Storage.
|
||||
|
||||
## Run Minio Gateway for Backblaze B2 Cloud Storage
|
||||
Please follow this [guide](https://www.backblaze.com/b2/docs/quick_account.html) to create an account on backblaze.com to obtain your access credentisals for B2 Cloud storage.
|
||||
Please follow this [guide](https://www.backblaze.com/b2/docs/quick_account.html) to create an account on backblaze.com to obtain your access credentials for B2 Cloud storage.
|
||||
|
||||
### Using Docker
|
||||
```
|
||||
docker run -p 9000:9000 --name b2-s3 \
|
||||
-e "MINIO_ACCESS_KEY=b2_accound_id" \
|
||||
-e "MINIO_ACCESS_KEY=b2_account_id" \
|
||||
-e "MINIO_SECRET_KEY=b2_application_key" \
|
||||
minio/minio:edge gateway b2
|
||||
minio/minio gateway b2
|
||||
```
|
||||
|
||||
### Using Binary
|
||||
```
|
||||
export MINIO_ACCESS_KEY=b2_account_id
|
||||
export MINIO_SECRET_KEY=b2_application_key
|
||||
minio gateway b2
|
||||
```
|
||||
|
||||
## Test using Minio Browser
|
||||
|
||||
@@ -53,7 +53,6 @@ mc ls mygcs
|
||||
```
|
||||
|
||||
### Known limitations
|
||||
|
||||
Gateway inherits the following GCS limitations:
|
||||
|
||||
- Maximum number of multipart parts per upload is 1024.
|
||||
@@ -67,6 +66,5 @@ Other limitations:
|
||||
## Explore Further
|
||||
- [`mc` command-line interface](https://docs.minio.io/docs/minio-client-quickstart-guide)
|
||||
- [`aws` command-line interface](https://docs.minio.io/docs/aws-cli-with-minio)
|
||||
- [`minfs` filesystem interface](http://docs.minio.io/docs/minfs-quickstart-guide)
|
||||
- [`minio-go` Go SDK](https://docs.minio.io/docs/golang-client-quickstart-guide)
|
||||
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ Minio Gateway adds Amazon S3 compatibility to NAS storage. You may run multiple
|
||||
docker run -p 9000:9000 --name nas-s3 \
|
||||
-e "MINIO_ACCESS_KEY=minio" \
|
||||
-e "MINIO_SECRET_KEY=minio123" \
|
||||
minio/minio:edge gateway nas /shared/nasvol
|
||||
minio/minio gateway nas /shared/nasvol
|
||||
```
|
||||
|
||||
### Using Binary
|
||||
|
||||
+2
-3
@@ -8,14 +8,14 @@ Minio Gateway adds Amazon S3 compatibility to Alibaba Cloud Object Storage Servi
|
||||
docker run -p 9000:9000 --name azure-s3 \
|
||||
-e "MINIO_ACCESS_KEY=ossaccesskey" \
|
||||
-e "MINIO_SECRET_KEY=osssecretkey" \
|
||||
minio/minio gateway azure
|
||||
minio/minio gateway oss
|
||||
```
|
||||
|
||||
### Using Binary
|
||||
```
|
||||
export MINIO_ACCESS_KEY=ossaccesskey
|
||||
export MINIO_SECRET_KEY=osssecretkey
|
||||
minio gateway azure
|
||||
minio gateway oss
|
||||
```
|
||||
|
||||
## Test using Minio Browser
|
||||
@@ -54,5 +54,4 @@ Other limitations:
|
||||
|
||||
- [`mc` command-line interface](https://docs.minio.io/docs/minio-client-quickstart-guide)
|
||||
- [`aws` command-line interface](https://docs.minio.io/docs/aws-cli-with-minio)
|
||||
- [`minfs` filesystem interface](http://docs.minio.io/docs/minfs-quickstart-guide)
|
||||
- [`minio-go` Go SDK](https://docs.minio.io/docs/golang-client-quickstart-guide)
|
||||
|
||||
@@ -5,7 +5,7 @@ version: '2'
|
||||
# 9001 through 9004.
|
||||
services:
|
||||
minio1:
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
volumes:
|
||||
- data4:/data
|
||||
ports:
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3.1'
|
||||
|
||||
services:
|
||||
minio1:
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
volumes:
|
||||
- minio1-data:/export
|
||||
ports:
|
||||
@@ -20,7 +20,7 @@ services:
|
||||
- access_key
|
||||
|
||||
minio2:
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
volumes:
|
||||
- minio2-data:/export
|
||||
ports:
|
||||
@@ -38,7 +38,7 @@ services:
|
||||
- access_key
|
||||
|
||||
minio3:
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
volumes:
|
||||
- minio3-data:/export
|
||||
ports:
|
||||
@@ -56,7 +56,7 @@ services:
|
||||
- access_key
|
||||
|
||||
minio4:
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
volumes:
|
||||
- minio4-data:/export
|
||||
ports:
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
minio1:
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
volumes:
|
||||
- minio4-data:/export
|
||||
ports:
|
||||
|
||||
@@ -123,7 +123,7 @@ spec:
|
||||
- name: data
|
||||
mountPath: "/data"
|
||||
# Pulls the lastest Minio image from Docker Hub
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
args:
|
||||
- server
|
||||
- /data
|
||||
@@ -302,7 +302,7 @@ spec:
|
||||
value: "minio"
|
||||
- name: MINIO_SECRET_KEY
|
||||
value: "minio123"
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
args:
|
||||
- server
|
||||
- http://minio-0.minio.default.svc.cluster.local/data
|
||||
@@ -484,7 +484,7 @@ spec:
|
||||
containers:
|
||||
- name: minio
|
||||
# Pulls the default Minio image from Docker Hub
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
args:
|
||||
- gateway
|
||||
- gcs
|
||||
|
||||
@@ -21,7 +21,7 @@ spec:
|
||||
value: "minio"
|
||||
- name: MINIO_SECRET_KEY
|
||||
value: "minio123"
|
||||
image: minio/minio:RELEASE.2018-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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-03-28T23-45-53Z`|
|
||||
| `imageTag` | Minio image tag. Possible values listed [here](https://hub.docker.com/r/minio/minio/tags/).| `RELEASE.2018-03-30T00-38-44Z`|
|
||||
| `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-03-28T23-45-53Z
|
||||
image: minio/minio:RELEASE.2018-03-30T00-38-44Z
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user