mirror of
https://github.com/minio/minio.git
synced 2025-01-26 14:13:16 -05:00
Return appropriate errors API versions changes across REST APIs (#8480)
This PR adds code to appropriately handle versioning issues that come up quite constantly across our API changes. Currently we were also routing our requests wrong which sort of made it harder to write a consistent error handling code to appropriately reject or honor requests. This PR potentially fixes issues - old mc is used against new minio release which is incompatible returns an appropriate for client action. - any older servers talking to each other, report appropriate error - incompatible peer servers should report error and reject the calls with appropriate error
This commit is contained in:
parent
07a556a10b
commit
4e63e0e372
@ -530,12 +530,6 @@ func (a adminAPIHandlers) TopLocksHandler(w http.ResponseWriter, r *http.Request
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method only allowed in Distributed XL mode.
|
|
||||||
if !globalIsDistXL {
|
|
||||||
writeErrorResponseJSON(ctx, w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
peerLocks := globalNotificationSys.GetLocks(ctx)
|
peerLocks := globalNotificationSys.GetLocks(ctx)
|
||||||
// Once we have received all the locks currently used from peers
|
// Once we have received all the locks currently used from peers
|
||||||
// add the local peer locks list as well.
|
// add the local peer locks list as well.
|
||||||
|
@ -188,7 +188,7 @@ func testServiceSignalReceiver(cmd cmdType, t *testing.T) {
|
|||||||
func getServiceCmdRequest(cmd cmdType, cred auth.Credentials) (*http.Request, error) {
|
func getServiceCmdRequest(cmd cmdType, cred auth.Credentials) (*http.Request, error) {
|
||||||
queryVal := url.Values{}
|
queryVal := url.Values{}
|
||||||
queryVal.Set("action", string(cmd.toServiceAction()))
|
queryVal.Set("action", string(cmd.toServiceAction()))
|
||||||
resource := adminAPIPathPrefix + "/service?" + queryVal.Encode()
|
resource := adminPathPrefix + adminAPIVersionPrefix + "/service?" + queryVal.Encode()
|
||||||
req, err := newTestRequest(http.MethodPost, resource, 0, nil)
|
req, err := newTestRequest(http.MethodPost, resource, 0, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -257,7 +257,7 @@ func buildAdminRequest(queryVal url.Values, method, path string,
|
|||||||
contentLength int64, bodySeeker io.ReadSeeker) (*http.Request, error) {
|
contentLength int64, bodySeeker io.ReadSeeker) (*http.Request, error) {
|
||||||
|
|
||||||
req, err := newTestRequest(method,
|
req, err := newTestRequest(method,
|
||||||
adminAPIPathPrefix+path+"?"+queryVal.Encode(),
|
adminPathPrefix+adminAPIVersionPrefix+path+"?"+queryVal.Encode(),
|
||||||
contentLength, bodySeeker)
|
contentLength, bodySeeker)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -24,138 +24,141 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
adminAPIPathPrefix = minioReservedBucketPath + "/admin/" + madmin.AdminAPIVersion
|
adminPathPrefix = minioReservedBucketPath + "/admin"
|
||||||
|
adminAPIVersion = madmin.AdminAPIVersion
|
||||||
|
adminAPIVersionPrefix = SlashSeparator + madmin.AdminAPIVersion
|
||||||
)
|
)
|
||||||
|
|
||||||
// adminAPIHandlers provides HTTP handlers for MinIO admin API.
|
// adminAPIHandlers provides HTTP handlers for MinIO admin API.
|
||||||
type adminAPIHandlers struct {
|
type adminAPIHandlers struct{}
|
||||||
}
|
|
||||||
|
|
||||||
// registerAdminRouter - Add handler functions for each service REST API routes.
|
// registerAdminRouter - Add handler functions for each service REST API routes.
|
||||||
func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool) {
|
func registerAdminRouter(router *mux.Router, enableConfigOps, enableIAMOps bool) {
|
||||||
|
|
||||||
adminAPI := adminAPIHandlers{}
|
adminAPI := adminAPIHandlers{}
|
||||||
// Admin router
|
// Admin router
|
||||||
adminRouter := router.PathPrefix(adminAPIPathPrefix).Subrouter()
|
adminRouter := router.PathPrefix(adminPathPrefix).Subrouter()
|
||||||
|
|
||||||
/// Service operations
|
/// Service operations
|
||||||
|
|
||||||
// Restart and stop MinIO service.
|
// Restart and stop MinIO service.
|
||||||
adminRouter.Methods(http.MethodPost).Path("/service").HandlerFunc(httpTraceAll(adminAPI.ServiceActionHandler)).Queries("action", "{action:.*}")
|
adminRouter.Methods(http.MethodPost).Path(adminAPIVersionPrefix+"/service").HandlerFunc(httpTraceAll(adminAPI.ServiceActionHandler)).Queries("action", "{action:.*}")
|
||||||
// Update MinIO servers.
|
// Update MinIO servers.
|
||||||
adminRouter.Methods(http.MethodPost).Path("/update").HandlerFunc(httpTraceAll(adminAPI.ServerUpdateHandler)).Queries("updateURL", "{updateURL:.*}")
|
adminRouter.Methods(http.MethodPost).Path(adminAPIVersionPrefix+"/update").HandlerFunc(httpTraceAll(adminAPI.ServerUpdateHandler)).Queries("updateURL", "{updateURL:.*}")
|
||||||
|
|
||||||
// Info operations
|
// Info operations
|
||||||
adminRouter.Methods(http.MethodGet).Path("/info").HandlerFunc(httpTraceAll(adminAPI.ServerInfoHandler))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/info").HandlerFunc(httpTraceAll(adminAPI.ServerInfoHandler))
|
||||||
// Harware Info operations
|
// Harware Info operations
|
||||||
adminRouter.Methods(http.MethodGet).Path("/hardware").HandlerFunc(httpTraceAll(adminAPI.ServerHardwareInfoHandler)).Queries("hwType", "{hwType:.*}")
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix+"/hardware").HandlerFunc(httpTraceAll(adminAPI.ServerHardwareInfoHandler)).Queries("hwType", "{hwType:.*}")
|
||||||
|
|
||||||
// StorageInfo operations
|
// StorageInfo operations
|
||||||
adminRouter.Methods(http.MethodGet).Path("/storageinfo").HandlerFunc(httpTraceAll(adminAPI.StorageInfoHandler))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/storageinfo").HandlerFunc(httpTraceAll(adminAPI.StorageInfoHandler))
|
||||||
|
|
||||||
if globalIsDistXL || globalIsXL {
|
if globalIsDistXL || globalIsXL {
|
||||||
/// Heal operations
|
/// Heal operations
|
||||||
|
|
||||||
// Heal processing endpoint.
|
// Heal processing endpoint.
|
||||||
adminRouter.Methods(http.MethodPost).Path("/heal/").HandlerFunc(httpTraceAll(adminAPI.HealHandler))
|
adminRouter.Methods(http.MethodPost).Path(adminAPIVersionPrefix + "/heal/").HandlerFunc(httpTraceAll(adminAPI.HealHandler))
|
||||||
adminRouter.Methods(http.MethodPost).Path("/heal/{bucket}").HandlerFunc(httpTraceAll(adminAPI.HealHandler))
|
adminRouter.Methods(http.MethodPost).Path(adminAPIVersionPrefix + "/heal/{bucket}").HandlerFunc(httpTraceAll(adminAPI.HealHandler))
|
||||||
adminRouter.Methods(http.MethodPost).Path("/heal/{bucket}/{prefix:.*}").HandlerFunc(httpTraceAll(adminAPI.HealHandler))
|
adminRouter.Methods(http.MethodPost).Path(adminAPIVersionPrefix + "/heal/{bucket}/{prefix:.*}").HandlerFunc(httpTraceAll(adminAPI.HealHandler))
|
||||||
|
|
||||||
adminRouter.Methods(http.MethodPost).Path("/background-heal/status").HandlerFunc(httpTraceAll(adminAPI.BackgroundHealStatusHandler))
|
adminRouter.Methods(http.MethodPost).Path(adminAPIVersionPrefix + "/background-heal/status").HandlerFunc(httpTraceAll(adminAPI.BackgroundHealStatusHandler))
|
||||||
|
|
||||||
/// Health operations
|
/// Health operations
|
||||||
|
|
||||||
}
|
}
|
||||||
// Performance command - return performance details based on input type
|
// Performance command - return performance details based on input type
|
||||||
adminRouter.Methods(http.MethodGet).Path("/performance").HandlerFunc(httpTraceAll(adminAPI.PerfInfoHandler)).Queries("perfType", "{perfType:.*}")
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix+"/performance").HandlerFunc(httpTraceAll(adminAPI.PerfInfoHandler)).Queries("perfType", "{perfType:.*}")
|
||||||
|
|
||||||
// Profiling operations
|
// Profiling operations
|
||||||
adminRouter.Methods(http.MethodPost).Path("/profiling/start").HandlerFunc(httpTraceAll(adminAPI.StartProfilingHandler)).
|
adminRouter.Methods(http.MethodPost).Path(adminAPIVersionPrefix+"/profiling/start").HandlerFunc(httpTraceAll(adminAPI.StartProfilingHandler)).
|
||||||
Queries("profilerType", "{profilerType:.*}")
|
Queries("profilerType", "{profilerType:.*}")
|
||||||
adminRouter.Methods(http.MethodGet).Path("/profiling/download").HandlerFunc(httpTraceAll(adminAPI.DownloadProfilingHandler))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/profiling/download").HandlerFunc(httpTraceAll(adminAPI.DownloadProfilingHandler))
|
||||||
|
|
||||||
// Config KV operations.
|
// Config KV operations.
|
||||||
if enableConfigOps {
|
if enableConfigOps {
|
||||||
adminRouter.Methods(http.MethodGet).Path("/get-config-kv").HandlerFunc(httpTraceHdrs(adminAPI.GetConfigKVHandler)).Queries("key", "{key:.*}")
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix+"/get-config-kv").HandlerFunc(httpTraceHdrs(adminAPI.GetConfigKVHandler)).Queries("key", "{key:.*}")
|
||||||
adminRouter.Methods(http.MethodPut).Path("/set-config-kv").HandlerFunc(httpTraceHdrs(adminAPI.SetConfigKVHandler))
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix + "/set-config-kv").HandlerFunc(httpTraceHdrs(adminAPI.SetConfigKVHandler))
|
||||||
adminRouter.Methods(http.MethodDelete).Path("/del-config-kv").HandlerFunc(httpTraceHdrs(adminAPI.DelConfigKVHandler))
|
adminRouter.Methods(http.MethodDelete).Path(adminAPIVersionPrefix + "/del-config-kv").HandlerFunc(httpTraceHdrs(adminAPI.DelConfigKVHandler))
|
||||||
adminRouter.Methods(http.MethodGet).Path("/help-config-kv").HandlerFunc(httpTraceAll(adminAPI.HelpConfigKVHandler)).Queries("subSys", "{subSys:.*}", "key", "{key:.*}")
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix+"/help-config-kv").HandlerFunc(httpTraceAll(adminAPI.HelpConfigKVHandler)).Queries("subSys", "{subSys:.*}", "key", "{key:.*}")
|
||||||
adminRouter.Methods(http.MethodGet).Path("/list-config-history-kv").HandlerFunc(httpTraceAll(adminAPI.ListConfigHistoryKVHandler))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/list-config-history-kv").HandlerFunc(httpTraceAll(adminAPI.ListConfigHistoryKVHandler))
|
||||||
adminRouter.Methods(http.MethodDelete).Path("/clear-config-history-kv").HandlerFunc(httpTraceHdrs(adminAPI.ClearConfigHistoryKVHandler)).Queries("restoreId", "{restoreId:.*}")
|
adminRouter.Methods(http.MethodDelete).Path(adminAPIVersionPrefix+"/clear-config-history-kv").HandlerFunc(httpTraceHdrs(adminAPI.ClearConfigHistoryKVHandler)).Queries("restoreId", "{restoreId:.*}")
|
||||||
adminRouter.Methods(http.MethodPut).Path("/restore-config-history-kv").HandlerFunc(httpTraceHdrs(adminAPI.RestoreConfigHistoryKVHandler)).Queries("restoreId", "{restoreId:.*}")
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix+"/restore-config-history-kv").HandlerFunc(httpTraceHdrs(adminAPI.RestoreConfigHistoryKVHandler)).Queries("restoreId", "{restoreId:.*}")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Config operations
|
/// Config operations
|
||||||
if enableConfigOps {
|
if enableConfigOps {
|
||||||
// Get config
|
// Get config
|
||||||
adminRouter.Methods(http.MethodGet).Path("/config").HandlerFunc(httpTraceHdrs(adminAPI.GetConfigHandler))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/config").HandlerFunc(httpTraceHdrs(adminAPI.GetConfigHandler))
|
||||||
// Set config
|
// Set config
|
||||||
adminRouter.Methods(http.MethodPut).Path("/config").HandlerFunc(httpTraceHdrs(adminAPI.SetConfigHandler))
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix + "/config").HandlerFunc(httpTraceHdrs(adminAPI.SetConfigHandler))
|
||||||
}
|
}
|
||||||
|
|
||||||
if enableIAMOps {
|
if enableIAMOps {
|
||||||
// -- IAM APIs --
|
// -- IAM APIs --
|
||||||
|
|
||||||
// Add policy IAM
|
// Add policy IAM
|
||||||
adminRouter.Methods(http.MethodPut).Path("/add-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.AddCannedPolicy)).Queries("name",
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix+"/add-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.AddCannedPolicy)).Queries("name",
|
||||||
"{name:.*}")
|
"{name:.*}")
|
||||||
|
|
||||||
// Add user IAM
|
// Add user IAM
|
||||||
adminRouter.Methods(http.MethodPut).Path("/add-user").HandlerFunc(httpTraceHdrs(adminAPI.AddUser)).Queries("accessKey", "{accessKey:.*}")
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix+"/add-user").HandlerFunc(httpTraceHdrs(adminAPI.AddUser)).Queries("accessKey", "{accessKey:.*}")
|
||||||
adminRouter.Methods(http.MethodPut).Path("/set-user-status").HandlerFunc(httpTraceHdrs(adminAPI.SetUserStatus)).
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix+"/set-user-status").HandlerFunc(httpTraceHdrs(adminAPI.SetUserStatus)).
|
||||||
Queries("accessKey", "{accessKey:.*}").Queries("status", "{status:.*}")
|
Queries("accessKey", "{accessKey:.*}").Queries("status", "{status:.*}")
|
||||||
|
|
||||||
// Info policy IAM
|
// Info policy IAM
|
||||||
adminRouter.Methods(http.MethodGet).Path("/info-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.InfoCannedPolicy)).Queries("name", "{name:.*}")
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix+"/info-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.InfoCannedPolicy)).Queries("name", "{name:.*}")
|
||||||
|
|
||||||
// Remove policy IAM
|
// Remove policy IAM
|
||||||
adminRouter.Methods(http.MethodDelete).Path("/remove-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.RemoveCannedPolicy)).Queries("name", "{name:.*}")
|
adminRouter.Methods(http.MethodDelete).Path(adminAPIVersionPrefix+"/remove-canned-policy").HandlerFunc(httpTraceHdrs(adminAPI.RemoveCannedPolicy)).Queries("name", "{name:.*}")
|
||||||
|
|
||||||
// Set user or group policy
|
// Set user or group policy
|
||||||
adminRouter.Methods(http.MethodPut).Path("/set-user-or-group-policy").
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix+"/set-user-or-group-policy").
|
||||||
HandlerFunc(httpTraceHdrs(adminAPI.SetPolicyForUserOrGroup)).
|
HandlerFunc(httpTraceHdrs(adminAPI.SetPolicyForUserOrGroup)).
|
||||||
Queries("policyName", "{policyName:.*}", "userOrGroup", "{userOrGroup:.*}", "isGroup", "{isGroup:true|false}")
|
Queries("policyName", "{policyName:.*}", "userOrGroup", "{userOrGroup:.*}", "isGroup", "{isGroup:true|false}")
|
||||||
|
|
||||||
// Remove user IAM
|
// Remove user IAM
|
||||||
adminRouter.Methods(http.MethodDelete).Path("/remove-user").HandlerFunc(httpTraceHdrs(adminAPI.RemoveUser)).Queries("accessKey", "{accessKey:.*}")
|
adminRouter.Methods(http.MethodDelete).Path(adminAPIVersionPrefix+"/remove-user").HandlerFunc(httpTraceHdrs(adminAPI.RemoveUser)).Queries("accessKey", "{accessKey:.*}")
|
||||||
|
|
||||||
// List users
|
// List users
|
||||||
adminRouter.Methods(http.MethodGet).Path("/list-users").HandlerFunc(httpTraceHdrs(adminAPI.ListUsers))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/list-users").HandlerFunc(httpTraceHdrs(adminAPI.ListUsers))
|
||||||
|
|
||||||
// User info
|
// User info
|
||||||
adminRouter.Methods(http.MethodGet).Path("/user-info").HandlerFunc(httpTraceHdrs(adminAPI.GetUserInfo)).Queries("accessKey", "{accessKey:.*}")
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix+"/user-info").HandlerFunc(httpTraceHdrs(adminAPI.GetUserInfo)).Queries("accessKey", "{accessKey:.*}")
|
||||||
|
|
||||||
// Add/Remove members from group
|
// Add/Remove members from group
|
||||||
adminRouter.Methods(http.MethodPut).Path("/update-group-members").HandlerFunc(httpTraceHdrs(adminAPI.UpdateGroupMembers))
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix + "/update-group-members").HandlerFunc(httpTraceHdrs(adminAPI.UpdateGroupMembers))
|
||||||
|
|
||||||
// Get Group
|
// Get Group
|
||||||
adminRouter.Methods(http.MethodGet).Path("/group").HandlerFunc(httpTraceHdrs(adminAPI.GetGroup)).Queries("group", "{group:.*}")
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix+"/group").HandlerFunc(httpTraceHdrs(adminAPI.GetGroup)).Queries("group", "{group:.*}")
|
||||||
|
|
||||||
// List Groups
|
// List Groups
|
||||||
adminRouter.Methods(http.MethodGet).Path("/groups").HandlerFunc(httpTraceHdrs(adminAPI.ListGroups))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/groups").HandlerFunc(httpTraceHdrs(adminAPI.ListGroups))
|
||||||
|
|
||||||
// Set Group Status
|
// Set Group Status
|
||||||
adminRouter.Methods(http.MethodPut).Path("/set-group-status").HandlerFunc(httpTraceHdrs(adminAPI.SetGroupStatus)).Queries("group", "{group:.*}").Queries("status", "{status:.*}")
|
adminRouter.Methods(http.MethodPut).Path(adminAPIVersionPrefix+"/set-group-status").HandlerFunc(httpTraceHdrs(adminAPI.SetGroupStatus)).Queries("group", "{group:.*}").Queries("status", "{status:.*}")
|
||||||
|
|
||||||
// List policies
|
// List policies
|
||||||
adminRouter.Methods(http.MethodGet).Path("/list-canned-policies").HandlerFunc(httpTraceHdrs(adminAPI.ListCannedPolicies))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/list-canned-policies").HandlerFunc(httpTraceHdrs(adminAPI.ListCannedPolicies))
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Top APIs --
|
// -- Top APIs --
|
||||||
// Top locks
|
// Top locks
|
||||||
adminRouter.Methods(http.MethodGet).Path("/top/locks").HandlerFunc(httpTraceHdrs(adminAPI.TopLocksHandler))
|
if globalIsDistXL {
|
||||||
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/top/locks").HandlerFunc(httpTraceHdrs(adminAPI.TopLocksHandler))
|
||||||
|
}
|
||||||
|
|
||||||
// HTTP Trace
|
// HTTP Trace
|
||||||
adminRouter.Methods(http.MethodGet).Path("/trace").HandlerFunc(adminAPI.TraceHandler)
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/trace").HandlerFunc(adminAPI.TraceHandler)
|
||||||
|
|
||||||
// Console Logs
|
// Console Logs
|
||||||
adminRouter.Methods(http.MethodGet).Path("/log").HandlerFunc(httpTraceAll(adminAPI.ConsoleLogHandler))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/log").HandlerFunc(httpTraceAll(adminAPI.ConsoleLogHandler))
|
||||||
|
|
||||||
// -- KMS APIs --
|
// -- KMS APIs --
|
||||||
//
|
//
|
||||||
adminRouter.Methods(http.MethodGet).Path("/kms/key/status").HandlerFunc(httpTraceAll(adminAPI.KMSKeyStatusHandler))
|
adminRouter.Methods(http.MethodGet).Path(adminAPIVersionPrefix + "/kms/key/status").HandlerFunc(httpTraceAll(adminAPI.KMSKeyStatusHandler))
|
||||||
|
|
||||||
// If none of the routes match, return error.
|
// If none of the routes match add default error handler routes
|
||||||
adminRouter.NotFoundHandler = http.HandlerFunc(httpTraceHdrs(notFoundHandler))
|
adminRouter.NotFoundHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
adminRouter.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(versionMismatchHandler))
|
adminRouter.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,6 @@ const (
|
|||||||
ErrInvalidPrefixMarker
|
ErrInvalidPrefixMarker
|
||||||
ErrBadRequest
|
ErrBadRequest
|
||||||
ErrKeyTooLongError
|
ErrKeyTooLongError
|
||||||
ErrInvalidAPIVersion
|
|
||||||
// Add new error codes here.
|
// Add new error codes here.
|
||||||
|
|
||||||
// SSE-S3 related API errors
|
// SSE-S3 related API errors
|
||||||
@ -1503,11 +1502,6 @@ var errorCodes = errorCodeMap{
|
|||||||
Description: "Invalid according to Policy: Policy Condition failed",
|
Description: "Invalid according to Policy: Policy Condition failed",
|
||||||
HTTPStatusCode: http.StatusForbidden,
|
HTTPStatusCode: http.StatusForbidden,
|
||||||
},
|
},
|
||||||
ErrInvalidAPIVersion: {
|
|
||||||
Code: "ErrInvalidAPIVersion",
|
|
||||||
Description: "Invalid version found in the request",
|
|
||||||
HTTPStatusCode: http.StatusNotFound,
|
|
||||||
},
|
|
||||||
// Add your error structure here.
|
// Add your error structure here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -694,6 +694,11 @@ func writeErrorResponseHeadersOnly(w http.ResponseWriter, err APIError) {
|
|||||||
writeResponse(w, err.HTTPStatusCode, nil, mimeNone)
|
writeResponse(w, err.HTTPStatusCode, nil, mimeNone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeErrorResponseString(ctx context.Context, w http.ResponseWriter, err APIError, reqURL *url.URL) {
|
||||||
|
// Generate string error response.
|
||||||
|
writeResponse(w, err.HTTPStatusCode, []byte(err.Description), mimeNone)
|
||||||
|
}
|
||||||
|
|
||||||
// writeErrorResponseJSON - writes error response in JSON format;
|
// writeErrorResponseJSON - writes error response in JSON format;
|
||||||
// useful for admin APIs.
|
// useful for admin APIs.
|
||||||
func writeErrorResponseJSON(ctx context.Context, w http.ResponseWriter, err APIError, reqURL *url.URL) {
|
func writeErrorResponseJSON(ctx context.Context, w http.ResponseWriter, err APIError, reqURL *url.URL) {
|
||||||
|
@ -171,6 +171,8 @@ func registerAPIRouter(router *mux.Router, encryptionEnabled, allowSSEKMS bool)
|
|||||||
// ListBuckets
|
// ListBuckets
|
||||||
apiRouter.Methods(http.MethodGet).Path(SlashSeparator).HandlerFunc(collectAPIStats("listbuckets", httpTraceAll(api.ListBucketsHandler)))
|
apiRouter.Methods(http.MethodGet).Path(SlashSeparator).HandlerFunc(collectAPIStats("listbuckets", httpTraceAll(api.ListBucketsHandler)))
|
||||||
|
|
||||||
// If none of the routes match.
|
// If none of the routes match add default error handler routes
|
||||||
apiRouter.NotFoundHandler = http.HandlerFunc(collectAPIStats("notfound", httpTraceAll(notFoundHandler)))
|
apiRouter.NotFoundHandler = http.HandlerFunc(collectAPIStats("notfound", httpTraceAll(errorResponseHandler)))
|
||||||
|
apiRouter.MethodNotAllowedHandler = http.HandlerFunc(collectAPIStats("methodnotallowed", httpTraceAll(errorResponseHandler)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,20 @@ func handleEncryptedConfigBackend(objAPI ObjectLayer, server bool) error {
|
|||||||
var encrypted bool
|
var encrypted bool
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
// Construct path to config/transaction.lock for locking
|
||||||
|
transactionConfigPrefix := minioConfigPrefix + "/transaction.lock"
|
||||||
|
|
||||||
|
// Make sure to hold lock for entire migration to avoid
|
||||||
|
// such that only one server should migrate the entire config
|
||||||
|
// at a given time, this big transaction lock ensures this
|
||||||
|
// appropriately. This is also true for rotation of encrypted
|
||||||
|
// content.
|
||||||
|
objLock := globalNSMutex.NewNSLock(context.Background(), minioMetaBucket, transactionConfigPrefix)
|
||||||
|
if err := objLock.GetLock(globalOperationTimeout); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer objLock.Unlock()
|
||||||
|
|
||||||
// Migrating Config backend needs a retry mechanism for
|
// Migrating Config backend needs a retry mechanism for
|
||||||
// the following reasons:
|
// the following reasons:
|
||||||
// - Read quorum is lost just after the initialization
|
// - Read quorum is lost just after the initialization
|
||||||
@ -48,8 +62,7 @@ func handleEncryptedConfigBackend(objAPI ObjectLayer, server bool) error {
|
|||||||
for range newRetryTimerSimple(doneCh) {
|
for range newRetryTimerSimple(doneCh) {
|
||||||
if encrypted, err = checkBackendEncrypted(objAPI); err != nil {
|
if encrypted, err = checkBackendEncrypted(objAPI); err != nil {
|
||||||
if err == errDiskNotFound ||
|
if err == errDiskNotFound ||
|
||||||
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) {
|
||||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
|
||||||
logger.Info("Waiting for config backend to be encrypted..")
|
logger.Info("Waiting for config backend to be encrypted..")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -247,18 +260,6 @@ func migrateConfigPrefixToEncrypted(objAPI ObjectLayer, activeCredOld auth.Crede
|
|||||||
logger.Info("Attempting a rotation of encrypted config, IAM users and policies on MinIO with newly supplied credentials")
|
logger.Info("Attempting a rotation of encrypted config, IAM users and policies on MinIO with newly supplied credentials")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct path to config/transaction.lock for locking
|
|
||||||
transactionConfigPrefix := minioConfigPrefix + "/transaction.lock"
|
|
||||||
|
|
||||||
// As object layer's GetObject() and PutObject() take respective lock on minioMetaBucket
|
|
||||||
// and configFile, take a transaction lock to avoid data race between readConfig()
|
|
||||||
// and saveConfig().
|
|
||||||
objLock := globalNSMutex.NewNSLock(context.Background(), minioMetaBucket, transactionConfigPrefix)
|
|
||||||
if err := objLock.GetLock(globalOperationTimeout); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer objLock.Unlock()
|
|
||||||
|
|
||||||
var marker string
|
var marker string
|
||||||
for {
|
for {
|
||||||
res, err := objAPI.ListObjects(context.Background(), minioMetaBucket, minioConfigPrefix, marker, "", maxObjectList)
|
res, err := objAPI.ListObjects(context.Background(), minioMetaBucket, minioConfigPrefix, marker, "", maxObjectList)
|
||||||
|
@ -2427,11 +2427,6 @@ func migrateConfigToMinioSys(objAPI ObjectLayer) (err error) {
|
|||||||
// Construct path to config.json for the given bucket.
|
// Construct path to config.json for the given bucket.
|
||||||
configFile := path.Join(minioConfigPrefix, minioConfigFile)
|
configFile := path.Join(minioConfigPrefix, minioConfigFile)
|
||||||
|
|
||||||
// Verify if config was already available in .minio.sys in which case, nothing more to be done.
|
|
||||||
if err = checkConfig(context.Background(), objAPI, configFile); err != errConfigNotFound {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if globalEtcdClient != nil {
|
if globalEtcdClient != nil {
|
||||||
@ -2444,18 +2439,6 @@ func migrateConfigToMinioSys(objAPI ObjectLayer) (err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Construct path to config/transaction.lock for locking
|
|
||||||
transactionConfigPrefix := minioConfigPrefix + "/transaction.lock"
|
|
||||||
|
|
||||||
// As object layer's GetObject() and PutObject() take respective lock on minioMetaBucket
|
|
||||||
// and configFile, take a transaction lock to avoid data race between readConfig()
|
|
||||||
// and saveConfig().
|
|
||||||
objLock := globalNSMutex.NewNSLock(context.Background(), minioMetaBucket, transactionConfigPrefix)
|
|
||||||
if err = objLock.GetLock(globalOperationTimeout); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer objLock.Unlock()
|
|
||||||
|
|
||||||
// Verify if backend already has the file (after holding lock)
|
// Verify if backend already has the file (after holding lock)
|
||||||
if err = checkConfig(context.Background(), objAPI, configFile); err != errConfigNotFound {
|
if err = checkConfig(context.Background(), objAPI, configFile); err != errConfigNotFound {
|
||||||
return err
|
return err
|
||||||
@ -2488,6 +2471,7 @@ func migrateConfigToMinioSys(objAPI ObjectLayer) (err error) {
|
|||||||
|
|
||||||
// Migrates '.minio.sys/config.json' to v33.
|
// Migrates '.minio.sys/config.json' to v33.
|
||||||
func migrateMinioSysConfig(objAPI ObjectLayer) error {
|
func migrateMinioSysConfig(objAPI ObjectLayer) error {
|
||||||
|
// Construct path to config.json for the given bucket.
|
||||||
configFile := path.Join(minioConfigPrefix, minioConfigFile)
|
configFile := path.Join(minioConfigPrefix, minioConfigFile)
|
||||||
|
|
||||||
// Check if the config version is latest, if not migrate.
|
// Check if the config version is latest, if not migrate.
|
||||||
@ -2499,18 +2483,6 @@ func migrateMinioSysConfig(objAPI ObjectLayer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct path to config/transaction.lock for locking
|
|
||||||
transactionConfigPrefix := minioConfigPrefix + "/transaction.lock"
|
|
||||||
|
|
||||||
// As object layer's GetObject() and PutObject() take respective lock on minioMetaBucket
|
|
||||||
// and configFile, take a transaction lock to avoid data race between readConfig()
|
|
||||||
// and saveConfig().
|
|
||||||
objLock := globalNSMutex.NewNSLock(context.Background(), minioMetaBucket, transactionConfigPrefix)
|
|
||||||
if err := objLock.GetLock(globalOperationTimeout); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer objLock.Unlock()
|
|
||||||
|
|
||||||
if err := migrateV27ToV28MinioSys(objAPI); err != nil {
|
if err := migrateV27ToV28MinioSys(objAPI); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2806,18 +2778,6 @@ func migrateMinioSysConfigToKV(objAPI ObjectLayer) error {
|
|||||||
notify.SetNotifyWebhook(newCfg, k, args)
|
notify.SetNotifyWebhook(newCfg, k, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct path to config/transaction.lock for locking
|
|
||||||
transactionConfigPrefix := minioConfigPrefix + "/transaction.lock"
|
|
||||||
|
|
||||||
// As object layer's GetObject() and PutObject() take respective lock on minioMetaBucket
|
|
||||||
// and configFile, take a transaction lock to avoid data race between readConfig()
|
|
||||||
// and saveConfig().
|
|
||||||
objLock := globalNSMutex.NewNSLock(context.Background(), minioMetaBucket, transactionConfigPrefix)
|
|
||||||
if err = objLock.GetLock(globalOperationTimeout); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer objLock.Unlock()
|
|
||||||
|
|
||||||
if err = saveServerConfig(context.Background(), objAPI, newCfg, cfg); err != nil {
|
if err = saveServerConfig(context.Background(), objAPI, newCfg, cfg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,8 @@ func (sys *ConfigSys) Init(objAPI ObjectLayer) error {
|
|||||||
select {
|
select {
|
||||||
case <-retryTimerCh:
|
case <-retryTimerCh:
|
||||||
if err := initConfig(objAPI); err != nil {
|
if err := initConfig(objAPI); err != nil {
|
||||||
if strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
if err == errDiskNotFound ||
|
||||||
|
strings.Contains(err.Error(), InsufficientReadQuorum{}.Error()) ||
|
||||||
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
strings.Contains(err.Error(), InsufficientWriteQuorum{}.Error()) {
|
||||||
logger.Info("Waiting for configuration to be initialized..")
|
logger.Info("Waiting for configuration to be initialized..")
|
||||||
continue
|
continue
|
||||||
@ -264,6 +265,19 @@ func initConfig(objAPI ObjectLayer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Construct path to config/transaction.lock for locking
|
||||||
|
transactionConfigPrefix := minioConfigPrefix + "/transaction.lock"
|
||||||
|
|
||||||
|
// Hold lock only by one server and let that server alone migrate
|
||||||
|
// all the config as necessary, this is to ensure that
|
||||||
|
// redundant locks are not held for each migration - this allows
|
||||||
|
// for a more predictable behavior while debugging.
|
||||||
|
objLock := globalNSMutex.NewNSLock(context.Background(), minioMetaBucket, transactionConfigPrefix)
|
||||||
|
if err := objLock.GetLock(globalOperationTimeout); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer objLock.Unlock()
|
||||||
|
|
||||||
// Migrates ${HOME}/.minio/config.json or config.json.deprecated
|
// Migrates ${HOME}/.minio/config.json or config.json.deprecated
|
||||||
// to '<export_path>/.minio.sys/config/config.json'
|
// to '<export_path>/.minio.sys/config/config.json'
|
||||||
// ignore if the file doesn't exist.
|
// ignore if the file doesn't exist.
|
||||||
|
@ -36,7 +36,7 @@ func TestDiskCacheFormat(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// Do the basic sanity checks to check if initFormatCache() did its job.
|
// Do the basic sanity checks to check if initFormatCache() did its job.
|
||||||
cacheFormatPath := pathJoin(fsDirs[0], minioMetaBucket, formatConfigFile)
|
cacheFormatPath := pathJoin(fsDirs[0], minioMetaBucket, formatConfigFile)
|
||||||
f, err := os.OpenFile(cacheFormatPath, os.O_RDWR, 0)
|
f, err := os.OpenFile(cacheFormatPath, os.O_RDWR|os.O_SYNC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ func TestFSFormatFS(t *testing.T) {
|
|||||||
rlk.Close()
|
rlk.Close()
|
||||||
|
|
||||||
// Do the basic sanity checks to check if initFormatFS() did its job.
|
// Do the basic sanity checks to check if initFormatFS() did its job.
|
||||||
f, err := os.OpenFile(fsFormatPath, os.O_RDWR, 0)
|
f, err := os.OpenFile(fsFormatPath, os.O_RDWR|os.O_SYNC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Check to allow access to the reserved "bucket" `/minio` for Admin
|
// Check to allow access to the reserved "bucket" `/minio` for Admin
|
||||||
// API requests.
|
// API requests.
|
||||||
func isAdminReq(r *http.Request) bool {
|
func isAdminReq(r *http.Request) bool {
|
||||||
return strings.HasPrefix(r.URL.Path, adminAPIPathPrefix+SlashSeparator)
|
return strings.HasPrefix(r.URL.Path, adminPathPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds verification for incoming paths.
|
// Adds verification for incoming paths.
|
||||||
@ -293,11 +293,11 @@ func (h minioReservedBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
|
|||||||
case guessIsRPCReq(r), guessIsBrowserReq(r), guessIsHealthCheckReq(r), guessIsMetricsReq(r), isAdminReq(r):
|
case guessIsRPCReq(r), guessIsBrowserReq(r), guessIsHealthCheckReq(r), guessIsMetricsReq(r), isAdminReq(r):
|
||||||
// Allow access to reserved buckets
|
// Allow access to reserved buckets
|
||||||
default:
|
default:
|
||||||
// For all other requests reject access to reserved
|
// For all other requests reject access to reserved buckets
|
||||||
// buckets
|
|
||||||
bucketName, _ := request2BucketObjectName(r)
|
bucketName, _ := request2BucketObjectName(r)
|
||||||
if isMinioReservedBucket(bucketName) || isMinioMetaBucket(bucketName) {
|
if isMinioReservedBucket(bucketName) || isMinioMetaBucket(bucketName) {
|
||||||
writeErrorResponse(context.Background(), w, errorCodes.ToAPIErr(ErrAllAccessDisabled), r.URL, guessIsBrowserReq(r))
|
browser := guessIsBrowserReq(r)
|
||||||
|
writeErrorResponse(r.Context(), w, errorCodes.ToAPIErr(ErrAllAccessDisabled), r.URL, browser)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,18 +19,21 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
xhttp "github.com/minio/minio/cmd/http"
|
xhttp "github.com/minio/minio/cmd/http"
|
||||||
"github.com/minio/minio/cmd/logger"
|
"github.com/minio/minio/cmd/logger"
|
||||||
"github.com/minio/minio/pkg/auth"
|
"github.com/minio/minio/pkg/auth"
|
||||||
"github.com/minio/minio/pkg/handlers"
|
"github.com/minio/minio/pkg/handlers"
|
||||||
|
"github.com/minio/minio/pkg/madmin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parses location constraint from the incoming reader.
|
// Parses location constraint from the incoming reader.
|
||||||
@ -408,23 +411,61 @@ func getResource(path string, host string, domains []string) (string, error) {
|
|||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none of the http routes match respond with MethodNotAllowed
|
var regexVersion = regexp.MustCompile(`(\w\d+)`)
|
||||||
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
writeErrorResponse(context.Background(), w, errorCodes.ToAPIErr(ErrMethodNotAllowed), r.URL, guessIsBrowserReq(r))
|
func extractAPIVersion(r *http.Request) string {
|
||||||
|
return regexVersion.FindString(r.URL.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the API version does not match with current version.
|
// If none of the http routes match respond with appropriate errors
|
||||||
func versionMismatchHandler(w http.ResponseWriter, r *http.Request) {
|
func errorResponseHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
path := r.URL.Path
|
version := extractAPIVersion(r)
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(path, minioReservedBucketPath+"/peer/"):
|
case strings.HasPrefix(r.URL.Path, peerRESTPrefix):
|
||||||
writeVersionMismatchResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInvalidAPIVersion), r.URL, false)
|
desc := fmt.Sprintf("Expected 'peer' API version '%s', instead found '%s', please upgrade the servers",
|
||||||
case strings.HasPrefix(path, minioReservedBucketPath+"/storage/"):
|
peerRESTVersion, version)
|
||||||
writeVersionMismatchResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInvalidAPIVersion), r.URL, false)
|
writeErrorResponseString(r.Context(), w, APIError{
|
||||||
case strings.HasPrefix(path, minioReservedBucketPath+"/lock/"):
|
Code: "XMinioPeerVersionMismatch",
|
||||||
writeVersionMismatchResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInvalidAPIVersion), r.URL, false)
|
Description: desc,
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
}, r.URL)
|
||||||
|
case strings.HasPrefix(r.URL.Path, storageRESTPrefix):
|
||||||
|
desc := fmt.Sprintf("Expected 'storage' API version '%s', instead found '%s', please upgrade the servers",
|
||||||
|
storageRESTVersion, version)
|
||||||
|
writeErrorResponseString(r.Context(), w, APIError{
|
||||||
|
Code: "XMinioStorageVersionMismatch",
|
||||||
|
Description: desc,
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
}, r.URL)
|
||||||
|
case strings.HasPrefix(r.URL.Path, lockRESTPrefix):
|
||||||
|
desc := fmt.Sprintf("Expected 'lock' API version '%s', instead found '%s', please upgrade the servers",
|
||||||
|
lockRESTVersion, version)
|
||||||
|
writeErrorResponseString(r.Context(), w, APIError{
|
||||||
|
Code: "XMinioLockVersionMismatch",
|
||||||
|
Description: desc,
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
}, r.URL)
|
||||||
|
case strings.HasPrefix(r.URL.Path, adminPathPrefix):
|
||||||
|
var desc string
|
||||||
|
if version == "v1" {
|
||||||
|
desc = fmt.Sprintf("Server expects client requests with 'admin' API version '%s', found '%s', please upgrade the client to latest releases", madmin.AdminAPIVersion, version)
|
||||||
|
} else if version == madmin.AdminAPIVersion {
|
||||||
|
desc = fmt.Sprintf("This 'admin' API is not supported by server in '%s'", getMinioMode())
|
||||||
|
} else {
|
||||||
|
desc = fmt.Sprintf("Unexpected client 'admin' API version found '%s', expected '%s', please downgrade the client to older releases", version, madmin.AdminAPIVersion)
|
||||||
|
}
|
||||||
|
writeErrorResponseJSON(r.Context(), w, APIError{
|
||||||
|
Code: "XMinioAdminVersionMismatch",
|
||||||
|
Description: desc,
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
}, r.URL)
|
||||||
default:
|
default:
|
||||||
writeVersionMismatchResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInvalidAPIVersion), r.URL, true)
|
desc := fmt.Sprintf("Unknown API request at %s", r.URL.Path)
|
||||||
|
writeErrorResponse(r.Context(), w, APIError{
|
||||||
|
Code: "XMinioUnknownAPIRequest",
|
||||||
|
Description: desc,
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
}, r.URL, guessIsBrowserReq(r))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,22 +18,23 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"path"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const lockRESTVersion = "v2"
|
const (
|
||||||
const lockRESTPath = minioReservedBucketPath + "/lock/" + lockRESTVersion
|
lockRESTVersion = "v2"
|
||||||
|
lockRESTVersionPrefix = SlashSeparator + "v2"
|
||||||
var lockServicePath = path.Join(minioReservedBucketPath, lockServiceSubPath)
|
lockRESTPrefix = minioReservedBucketPath + "/lock"
|
||||||
|
lockRESTPath = lockRESTPrefix + lockRESTVersionPrefix
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
lockRESTMethodLock = "lock"
|
lockRESTMethodLock = "/lock"
|
||||||
lockRESTMethodRLock = "rlock"
|
lockRESTMethodRLock = "/rlock"
|
||||||
lockRESTMethodUnlock = "unlock"
|
lockRESTMethodUnlock = "/unlock"
|
||||||
lockRESTMethodRUnlock = "runlock"
|
lockRESTMethodRUnlock = "/runlock"
|
||||||
lockRESTMethodForceUnlock = "forceunlock"
|
lockRESTMethodForceUnlock = "/forceunlock"
|
||||||
lockRESTMethodExpired = "expired"
|
lockRESTMethodExpired = "/expired"
|
||||||
|
|
||||||
// Unique ID of lock/unlock request.
|
// Unique ID of lock/unlock request.
|
||||||
lockRESTUID = "uid"
|
lockRESTUID = "uid"
|
||||||
|
@ -30,9 +30,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Lock rpc server endpoint.
|
|
||||||
lockServiceSubPath = "/lock"
|
|
||||||
|
|
||||||
// Lock maintenance interval.
|
// Lock maintenance interval.
|
||||||
lockMaintenanceInterval = 1 * time.Minute
|
lockMaintenanceInterval = 1 * time.Minute
|
||||||
|
|
||||||
@ -246,16 +243,18 @@ func startLockMaintenance(lkSrv *lockRESTServer) {
|
|||||||
|
|
||||||
// registerLockRESTHandlers - register lock rest router.
|
// registerLockRESTHandlers - register lock rest router.
|
||||||
func registerLockRESTHandlers(router *mux.Router) {
|
func registerLockRESTHandlers(router *mux.Router) {
|
||||||
subrouter := router.PathPrefix(lockRESTPath).Subrouter()
|
subrouter := router.PathPrefix(lockRESTPrefix).Subrouter()
|
||||||
queries := restQueries(lockRESTUID, lockRESTSource, lockRESTResource, lockRESTServerAddr, lockRESTServerEndpoint)
|
queries := restQueries(lockRESTUID, lockRESTSource, lockRESTResource, lockRESTServerAddr, lockRESTServerEndpoint)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodLock).HandlerFunc(httpTraceHdrs(globalLockServer.LockHandler)).Queries(queries...)
|
subrouter.Methods(http.MethodPost).Path(lockRESTVersionPrefix + lockRESTMethodLock).HandlerFunc(httpTraceHdrs(globalLockServer.LockHandler)).Queries(queries...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodRLock).HandlerFunc(httpTraceHdrs(globalLockServer.RLockHandler)).Queries(queries...)
|
subrouter.Methods(http.MethodPost).Path(lockRESTVersionPrefix + lockRESTMethodRLock).HandlerFunc(httpTraceHdrs(globalLockServer.RLockHandler)).Queries(queries...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.UnlockHandler)).Queries(queries...)
|
subrouter.Methods(http.MethodPost).Path(lockRESTVersionPrefix + lockRESTMethodUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.UnlockHandler)).Queries(queries...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodRUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.RUnlockHandler)).Queries(queries...)
|
subrouter.Methods(http.MethodPost).Path(lockRESTVersionPrefix + lockRESTMethodRUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.RUnlockHandler)).Queries(queries...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodForceUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.ForceUnlockHandler)).Queries(queries...)
|
subrouter.Methods(http.MethodPost).Path(lockRESTVersionPrefix + lockRESTMethodForceUnlock).HandlerFunc(httpTraceHdrs(globalLockServer.ForceUnlockHandler)).Queries(queries...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + lockRESTMethodExpired).HandlerFunc(httpTraceAll(globalLockServer.ExpiredHandler)).Queries(queries...)
|
subrouter.Methods(http.MethodPost).Path(lockRESTVersionPrefix + lockRESTMethodExpired).HandlerFunc(httpTraceAll(globalLockServer.ExpiredHandler)).Queries(queries...)
|
||||||
|
|
||||||
router.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(versionMismatchHandler))
|
// If none of the routes match add default error handler routes
|
||||||
|
router.NotFoundHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
|
router.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
|
|
||||||
// Start lock maintenance from all lock servers.
|
// Start lock maintenance from all lock servers.
|
||||||
go startLockMaintenance(globalLockServer)
|
go startLockMaintenance(globalLockServer)
|
||||||
|
@ -70,7 +70,7 @@ func newDsyncNodes(endpoints EndpointList) (clnts []dsync.NetLocker, myNode int,
|
|||||||
globalLockServer = &lockRESTServer{
|
globalLockServer = &lockRESTServer{
|
||||||
ll: &localLocker{
|
ll: &localLocker{
|
||||||
serverAddr: endpoint.Host,
|
serverAddr: endpoint.Host,
|
||||||
serviceEndpoint: lockServicePath,
|
serviceEndpoint: lockRESTPrefix,
|
||||||
lockMap: make(map[string][]lockRequesterInfo),
|
lockMap: make(map[string][]lockRequesterInfo),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -16,44 +16,48 @@
|
|||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
const peerRESTVersion = "v6"
|
const (
|
||||||
const peerRESTPath = minioReservedBucketPath + "/peer/" + peerRESTVersion
|
peerRESTVersion = "v6"
|
||||||
|
peerRESTVersionPrefix = SlashSeparator + peerRESTVersion
|
||||||
|
peerRESTPrefix = minioReservedBucketPath + "/peer"
|
||||||
|
peerRESTPath = peerRESTPrefix + peerRESTVersionPrefix
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
peerRESTMethodNetReadPerfInfo = "netreadperfinfo"
|
peerRESTMethodNetReadPerfInfo = "/netreadperfinfo"
|
||||||
peerRESTMethodCollectNetPerfInfo = "collectnetperfinfo"
|
peerRESTMethodCollectNetPerfInfo = "/collectnetperfinfo"
|
||||||
peerRESTMethodServerInfo = "serverinfo"
|
peerRESTMethodServerInfo = "/serverinfo"
|
||||||
peerRESTMethodCPULoadInfo = "cpuloadinfo"
|
peerRESTMethodCPULoadInfo = "/cpuloadinfo"
|
||||||
peerRESTMethodMemUsageInfo = "memusageinfo"
|
peerRESTMethodMemUsageInfo = "/memusageinfo"
|
||||||
peerRESTMethodDrivePerfInfo = "driveperfinfo"
|
peerRESTMethodDrivePerfInfo = "/driveperfinfo"
|
||||||
peerRESTMethodDeleteBucket = "deletebucket"
|
peerRESTMethodDeleteBucket = "/deletebucket"
|
||||||
peerRESTMethodServerUpdate = "serverupdate"
|
peerRESTMethodServerUpdate = "/serverupdate"
|
||||||
peerRESTMethodSignalService = "signalservice"
|
peerRESTMethodSignalService = "/signalservice"
|
||||||
peerRESTMethodBackgroundHealStatus = "backgroundhealstatus"
|
peerRESTMethodBackgroundHealStatus = "/backgroundhealstatus"
|
||||||
peerRESTMethodBackgroundOpsStatus = "backgroundopsstatus"
|
peerRESTMethodBackgroundOpsStatus = "/backgroundopsstatus"
|
||||||
peerRESTMethodGetLocks = "getlocks"
|
peerRESTMethodGetLocks = "/getlocks"
|
||||||
peerRESTMethodBucketPolicyRemove = "removebucketpolicy"
|
peerRESTMethodBucketPolicyRemove = "/removebucketpolicy"
|
||||||
peerRESTMethodLoadUser = "loaduser"
|
peerRESTMethodLoadUser = "/loaduser"
|
||||||
peerRESTMethodDeleteUser = "deleteuser"
|
peerRESTMethodDeleteUser = "/deleteuser"
|
||||||
peerRESTMethodLoadPolicy = "loadpolicy"
|
peerRESTMethodLoadPolicy = "/loadpolicy"
|
||||||
peerRESTMethodLoadPolicyMapping = "loadpolicymapping"
|
peerRESTMethodLoadPolicyMapping = "/loadpolicymapping"
|
||||||
peerRESTMethodDeletePolicy = "deletepolicy"
|
peerRESTMethodDeletePolicy = "/deletepolicy"
|
||||||
peerRESTMethodLoadUsers = "loadusers"
|
peerRESTMethodLoadUsers = "/loadusers"
|
||||||
peerRESTMethodLoadGroup = "loadgroup"
|
peerRESTMethodLoadGroup = "/loadgroup"
|
||||||
peerRESTMethodStartProfiling = "startprofiling"
|
peerRESTMethodStartProfiling = "/startprofiling"
|
||||||
peerRESTMethodDownloadProfilingData = "downloadprofilingdata"
|
peerRESTMethodDownloadProfilingData = "/downloadprofilingdata"
|
||||||
peerRESTMethodBucketPolicySet = "setbucketpolicy"
|
peerRESTMethodBucketPolicySet = "/setbucketpolicy"
|
||||||
peerRESTMethodBucketNotificationPut = "putbucketnotification"
|
peerRESTMethodBucketNotificationPut = "/putbucketnotification"
|
||||||
peerRESTMethodBucketNotificationListen = "listenbucketnotification"
|
peerRESTMethodBucketNotificationListen = "/listenbucketnotification"
|
||||||
peerRESTMethodReloadFormat = "reloadformat"
|
peerRESTMethodReloadFormat = "/reloadformat"
|
||||||
peerRESTMethodTargetExists = "targetexists"
|
peerRESTMethodTargetExists = "/targetexists"
|
||||||
peerRESTMethodSendEvent = "sendevent"
|
peerRESTMethodSendEvent = "/sendevent"
|
||||||
peerRESTMethodTrace = "trace"
|
peerRESTMethodTrace = "/trace"
|
||||||
peerRESTMethodBucketLifecycleSet = "setbucketlifecycle"
|
peerRESTMethodBucketLifecycleSet = "/setbucketlifecycle"
|
||||||
peerRESTMethodBucketLifecycleRemove = "removebucketlifecycle"
|
peerRESTMethodBucketLifecycleRemove = "/removebucketlifecycle"
|
||||||
peerRESTMethodLog = "log"
|
peerRESTMethodLog = "/log"
|
||||||
peerRESTMethodHardwareCPUInfo = "cpuhardwareinfo"
|
peerRESTMethodHardwareCPUInfo = "/cpuhardwareinfo"
|
||||||
peerRESTMethodHardwareNetworkInfo = "networkhardwareinfo"
|
peerRESTMethodHardwareNetworkInfo = "/networkhardwareinfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -995,47 +995,49 @@ func (s *peerRESTServer) IsValid(w http.ResponseWriter, r *http.Request) bool {
|
|||||||
// registerPeerRESTHandlers - register peer rest router.
|
// registerPeerRESTHandlers - register peer rest router.
|
||||||
func registerPeerRESTHandlers(router *mux.Router) {
|
func registerPeerRESTHandlers(router *mux.Router) {
|
||||||
server := &peerRESTServer{}
|
server := &peerRESTServer{}
|
||||||
subrouter := router.PathPrefix(peerRESTPath).Subrouter()
|
subrouter := router.PathPrefix(peerRESTPrefix).Subrouter()
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodNetReadPerfInfo).HandlerFunc(httpTraceHdrs(server.NetReadPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodNetReadPerfInfo).HandlerFunc(httpTraceHdrs(server.NetReadPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodCollectNetPerfInfo).HandlerFunc(httpTraceHdrs(server.CollectNetPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCollectNetPerfInfo).HandlerFunc(httpTraceHdrs(server.CollectNetPerfInfoHandler)).Queries(restQueries(peerRESTNetPerfSize)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodGetLocks).HandlerFunc(httpTraceHdrs(server.GetLocksHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodGetLocks).HandlerFunc(httpTraceHdrs(server.GetLocksHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodCPULoadInfo).HandlerFunc(httpTraceHdrs(server.CPULoadInfoHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodCPULoadInfo).HandlerFunc(httpTraceHdrs(server.CPULoadInfoHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodMemUsageInfo).HandlerFunc(httpTraceHdrs(server.MemUsageInfoHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMemUsageInfo).HandlerFunc(httpTraceHdrs(server.MemUsageInfoHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDrivePerfInfo).HandlerFunc(httpTraceHdrs(server.DrivePerfInfoHandler)).Queries(restQueries(peerRESTDrivePerfSize)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDrivePerfInfo).HandlerFunc(httpTraceHdrs(server.DrivePerfInfoHandler)).Queries(restQueries(peerRESTDrivePerfSize)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodHardwareCPUInfo).HandlerFunc(httpTraceHdrs(server.CPUInfoHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodHardwareCPUInfo).HandlerFunc(httpTraceHdrs(server.CPUInfoHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodHardwareNetworkInfo).HandlerFunc(httpTraceHdrs(server.NetworkInfoHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodHardwareNetworkInfo).HandlerFunc(httpTraceHdrs(server.NetworkInfoHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeleteBucket).HandlerFunc(httpTraceHdrs(server.DeleteBucketHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteBucket).HandlerFunc(httpTraceHdrs(server.DeleteBucketHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodSignalService).HandlerFunc(httpTraceHdrs(server.SignalServiceHandler)).Queries(restQueries(peerRESTSignal)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSignalService).HandlerFunc(httpTraceHdrs(server.SignalServiceHandler)).Queries(restQueries(peerRESTSignal)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodServerUpdate).HandlerFunc(httpTraceHdrs(server.ServerUpdateHandler)).Queries(restQueries(peerRESTUpdateURL, peerRESTSha256Hex, peerRESTLatestRelease)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerUpdate).HandlerFunc(httpTraceHdrs(server.ServerUpdateHandler)).Queries(restQueries(peerRESTUpdateURL, peerRESTSha256Hex, peerRESTLatestRelease)...)
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketPolicyRemove).HandlerFunc(httpTraceAll(server.RemoveBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBucketPolicyRemove).HandlerFunc(httpTraceAll(server.RemoveBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketPolicySet).HandlerFunc(httpTraceHdrs(server.SetBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBucketPolicySet).HandlerFunc(httpTraceHdrs(server.SetBucketPolicyHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeletePolicy).HandlerFunc(httpTraceAll(server.DeletePolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeletePolicy).HandlerFunc(httpTraceAll(server.DeletePolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadPolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadPolicy).HandlerFunc(httpTraceAll(server.LoadPolicyHandler)).Queries(restQueries(peerRESTPolicy)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadPolicyMapping).HandlerFunc(httpTraceAll(server.LoadPolicyMappingHandler)).Queries(restQueries(peerRESTUserOrGroup)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadPolicyMapping).HandlerFunc(httpTraceAll(server.LoadPolicyMappingHandler)).Queries(restQueries(peerRESTUserOrGroup)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDeleteUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDeleteUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadUser).HandlerFunc(httpTraceAll(server.LoadUserHandler)).Queries(restQueries(peerRESTUser, peerRESTUserTemp)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadUsers).HandlerFunc(httpTraceAll(server.LoadUsersHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadUsers).HandlerFunc(httpTraceAll(server.LoadUsersHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLoadGroup).HandlerFunc(httpTraceAll(server.LoadGroupHandler)).Queries(restQueries(peerRESTGroup)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLoadGroup).HandlerFunc(httpTraceAll(server.LoadGroupHandler)).Queries(restQueries(peerRESTGroup)...)
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodStartProfiling).HandlerFunc(httpTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodStartProfiling).HandlerFunc(httpTraceAll(server.StartProfilingHandler)).Queries(restQueries(peerRESTProfiler)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodDownloadProfilingData).HandlerFunc(httpTraceHdrs(server.DownloadProflingDataHandler))
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodDownloadProfilingData).HandlerFunc(httpTraceHdrs(server.DownloadProflingDataHandler))
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodTargetExists).HandlerFunc(httpTraceHdrs(server.TargetExistsHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodTargetExists).HandlerFunc(httpTraceHdrs(server.TargetExistsHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodSendEvent).HandlerFunc(httpTraceHdrs(server.SendEventHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSendEvent).HandlerFunc(httpTraceHdrs(server.SendEventHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketNotificationPut).HandlerFunc(httpTraceHdrs(server.PutBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBucketNotificationPut).HandlerFunc(httpTraceHdrs(server.PutBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketNotificationListen).HandlerFunc(httpTraceHdrs(server.ListenBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBucketNotificationListen).HandlerFunc(httpTraceHdrs(server.ListenBucketNotificationHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodReloadFormat).HandlerFunc(httpTraceHdrs(server.ReloadFormatHandler)).Queries(restQueries(peerRESTDryRun)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodReloadFormat).HandlerFunc(httpTraceHdrs(server.ReloadFormatHandler)).Queries(restQueries(peerRESTDryRun)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketLifecycleSet).HandlerFunc(httpTraceHdrs(server.SetBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBucketLifecycleSet).HandlerFunc(httpTraceHdrs(server.SetBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBucketLifecycleRemove).HandlerFunc(httpTraceHdrs(server.RemoveBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBucketLifecycleRemove).HandlerFunc(httpTraceHdrs(server.RemoveBucketLifecycleHandler)).Queries(restQueries(peerRESTBucket)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBackgroundOpsStatus).HandlerFunc(server.BackgroundOpsStatusHandler)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBackgroundOpsStatus).HandlerFunc(server.BackgroundOpsStatusHandler)
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodTrace).HandlerFunc(server.TraceHandler)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodTrace).HandlerFunc(server.TraceHandler)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodBackgroundHealStatus).HandlerFunc(server.BackgroundHealStatusHandler)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodBackgroundHealStatus).HandlerFunc(server.BackgroundHealStatusHandler)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + peerRESTMethodLog).HandlerFunc(server.ConsoleLogHandler)
|
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodLog).HandlerFunc(server.ConsoleLogHandler)
|
||||||
|
|
||||||
router.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(versionMismatchHandler))
|
// If none of the routes match add default error handler routes
|
||||||
|
router.NotFoundHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
|
router.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
}
|
}
|
||||||
|
@ -1887,7 +1887,7 @@ func TestPosixVerifyFile(t *testing.T) {
|
|||||||
|
|
||||||
// 4) Streaming bitrot check on corrupted file
|
// 4) Streaming bitrot check on corrupted file
|
||||||
filePath := pathJoin(posixStorage.String(), volName, fileName)
|
filePath := pathJoin(posixStorage.String(), volName, fileName)
|
||||||
f, err := os.OpenFile(filePath, os.O_WRONLY, 0644)
|
f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_SYNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -54,13 +54,12 @@ type Client struct {
|
|||||||
|
|
||||||
// URL query separator constants
|
// URL query separator constants
|
||||||
const (
|
const (
|
||||||
resourceSep = "/"
|
querySep = "?"
|
||||||
querySep = "?"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CallWithContext - make a REST call with context.
|
// CallWithContext - make a REST call with context.
|
||||||
func (c *Client) CallWithContext(ctx context.Context, method string, values url.Values, body io.Reader, length int64) (reply io.ReadCloser, err error) {
|
func (c *Client) CallWithContext(ctx context.Context, method string, values url.Values, body io.Reader, length int64) (reply io.ReadCloser, err error) {
|
||||||
req, err := http.NewRequest(http.MethodPost, c.url.String()+resourceSep+method+querySep+values.Encode(), body)
|
req, err := http.NewRequest(http.MethodPost, c.url.String()+method+querySep+values.Encode(), body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &NetworkError{err}
|
return nil, &NetworkError{err}
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,9 @@ func serverMain(ctx *cli.Context) {
|
|||||||
// Handle all server command args.
|
// Handle all server command args.
|
||||||
serverHandleCmdArgs(ctx)
|
serverHandleCmdArgs(ctx)
|
||||||
|
|
||||||
|
// Handle all server environment vars.
|
||||||
|
serverHandleEnvVars()
|
||||||
|
|
||||||
// Check and load TLS certificates.
|
// Check and load TLS certificates.
|
||||||
var err error
|
var err error
|
||||||
globalPublicCerts, globalTLSCerts, globalIsSSL, err = getTLSConfig()
|
globalPublicCerts, globalTLSCerts, globalIsSSL, err = getTLSConfig()
|
||||||
@ -253,9 +256,6 @@ func serverMain(ctx *cli.Context) {
|
|||||||
globalRootCAs, err = config.GetRootCAs(globalCertsCADir.Get())
|
globalRootCAs, err = config.GetRootCAs(globalCertsCADir.Get())
|
||||||
logger.FatalIf(err, "Failed to read root CAs (%v)", err)
|
logger.FatalIf(err, "Failed to read root CAs (%v)", err)
|
||||||
|
|
||||||
// Handle all server environment vars.
|
|
||||||
serverHandleEnvVars()
|
|
||||||
|
|
||||||
// Is distributed setup, error out if no certificates are found for HTTPS endpoints.
|
// Is distributed setup, error out if no certificates are found for HTTPS endpoints.
|
||||||
if globalIsDistXL {
|
if globalIsDistXL {
|
||||||
if globalEndpoints.IsHTTPS() && !globalIsSSL {
|
if globalEndpoints.IsHTTPS() && !globalIsSSL {
|
||||||
|
@ -460,7 +460,7 @@ func newStorageRESTClient(endpoint Endpoint) (*storageRESTClient, error) {
|
|||||||
serverURL := &url.URL{
|
serverURL := &url.URL{
|
||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
Host: endpoint.Host,
|
Host: endpoint.Host,
|
||||||
Path: path.Join(storageRESTPath, endpoint.Path),
|
Path: path.Join(storageRESTPrefix, endpoint.Path, storageRESTVersion),
|
||||||
}
|
}
|
||||||
|
|
||||||
var tlsConfig *tls.Config
|
var tlsConfig *tls.Config
|
||||||
|
@ -17,30 +17,31 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
const (
|
const (
|
||||||
storageRESTVersion = "v10"
|
storageRESTVersion = "v10"
|
||||||
storageRESTPath = minioReservedBucketPath + "/storage/" + storageRESTVersion + SlashSeparator
|
storageRESTVersionPrefix = SlashSeparator + "v10"
|
||||||
|
storageRESTPrefix = minioReservedBucketPath + "/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
storageRESTMethodDiskInfo = "diskinfo"
|
storageRESTMethodDiskInfo = "/diskinfo"
|
||||||
storageRESTMethodMakeVol = "makevol"
|
storageRESTMethodMakeVol = "/makevol"
|
||||||
storageRESTMethodStatVol = "statvol"
|
storageRESTMethodStatVol = "/statvol"
|
||||||
storageRESTMethodDeleteVol = "deletevol"
|
storageRESTMethodDeleteVol = "/deletevol"
|
||||||
storageRESTMethodListVols = "listvols"
|
storageRESTMethodListVols = "/listvols"
|
||||||
|
|
||||||
storageRESTMethodAppendFile = "appendfile"
|
storageRESTMethodAppendFile = "/appendfile"
|
||||||
storageRESTMethodCreateFile = "createfile"
|
storageRESTMethodCreateFile = "/createfile"
|
||||||
storageRESTMethodWriteAll = "writeall"
|
storageRESTMethodWriteAll = "/writeall"
|
||||||
storageRESTMethodStatFile = "statfile"
|
storageRESTMethodStatFile = "/statfile"
|
||||||
storageRESTMethodReadAll = "readall"
|
storageRESTMethodReadAll = "/readall"
|
||||||
storageRESTMethodReadFile = "readfile"
|
storageRESTMethodReadFile = "/readfile"
|
||||||
storageRESTMethodReadFileStream = "readfilestream"
|
storageRESTMethodReadFileStream = "/readfilestream"
|
||||||
storageRESTMethodListDir = "listdir"
|
storageRESTMethodListDir = "/listdir"
|
||||||
storageRESTMethodWalk = "walk"
|
storageRESTMethodWalk = "/walk"
|
||||||
storageRESTMethodDeleteFile = "deletefile"
|
storageRESTMethodDeleteFile = "/deletefile"
|
||||||
storageRESTMethodDeleteFileBulk = "deletefilebulk"
|
storageRESTMethodDeleteFileBulk = "/deletefilebulk"
|
||||||
storageRESTMethodRenameFile = "renamefile"
|
storageRESTMethodRenameFile = "/renamefile"
|
||||||
storageRESTMethodVerifyFile = "verifyfile"
|
storageRESTMethodVerifyFile = "/verifyfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -573,43 +573,45 @@ func registerStorageRESTHandlers(router *mux.Router, endpoints EndpointList) {
|
|||||||
|
|
||||||
server := &storageRESTServer{storage: storage}
|
server := &storageRESTServer{storage: storage}
|
||||||
|
|
||||||
subrouter := router.PathPrefix(path.Join(storageRESTPath, endpoint.Path)).Subrouter()
|
subrouter := router.PathPrefix(path.Join(storageRESTPrefix, endpoint.Path)).Subrouter()
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDiskInfo).HandlerFunc(httpTraceHdrs(server.DiskInfoHandler))
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodDiskInfo).HandlerFunc(httpTraceHdrs(server.DiskInfoHandler))
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodMakeVol).HandlerFunc(httpTraceHdrs(server.MakeVolHandler)).Queries(restQueries(storageRESTVolume)...)
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodMakeVol).HandlerFunc(httpTraceHdrs(server.MakeVolHandler)).Queries(restQueries(storageRESTVolume)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodStatVol).HandlerFunc(httpTraceHdrs(server.StatVolHandler)).Queries(restQueries(storageRESTVolume)...)
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodStatVol).HandlerFunc(httpTraceHdrs(server.StatVolHandler)).Queries(restQueries(storageRESTVolume)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDeleteVol).HandlerFunc(httpTraceHdrs(server.DeleteVolHandler)).Queries(restQueries(storageRESTVolume)...)
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodDeleteVol).HandlerFunc(httpTraceHdrs(server.DeleteVolHandler)).Queries(restQueries(storageRESTVolume)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodListVols).HandlerFunc(httpTraceHdrs(server.ListVolsHandler))
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodListVols).HandlerFunc(httpTraceHdrs(server.ListVolsHandler))
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodAppendFile).HandlerFunc(httpTraceHdrs(server.AppendFileHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodAppendFile).HandlerFunc(httpTraceHdrs(server.AppendFileHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodWriteAll).HandlerFunc(httpTraceHdrs(server.WriteAllHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodWriteAll).HandlerFunc(httpTraceHdrs(server.WriteAllHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodCreateFile).HandlerFunc(httpTraceHdrs(server.CreateFileHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodCreateFile).HandlerFunc(httpTraceHdrs(server.CreateFileHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTLength)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTLength)...)
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodStatFile).HandlerFunc(httpTraceHdrs(server.StatFileHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodStatFile).HandlerFunc(httpTraceHdrs(server.StatFileHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodReadAll).HandlerFunc(httpTraceHdrs(server.ReadAllHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodReadAll).HandlerFunc(httpTraceHdrs(server.ReadAllHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodReadFile).HandlerFunc(httpTraceHdrs(server.ReadFileHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodReadFile).HandlerFunc(httpTraceHdrs(server.ReadFileHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTOffset, storageRESTLength, storageRESTBitrotAlgo, storageRESTBitrotHash)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTOffset, storageRESTLength, storageRESTBitrotAlgo, storageRESTBitrotHash)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodReadFileStream).HandlerFunc(httpTraceHdrs(server.ReadFileStreamHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodReadFileStream).HandlerFunc(httpTraceHdrs(server.ReadFileStreamHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTOffset, storageRESTLength)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTOffset, storageRESTLength)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodListDir).HandlerFunc(httpTraceHdrs(server.ListDirHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodListDir).HandlerFunc(httpTraceHdrs(server.ListDirHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTDirPath, storageRESTCount, storageRESTLeafFile)...)
|
Queries(restQueries(storageRESTVolume, storageRESTDirPath, storageRESTCount, storageRESTLeafFile)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodWalk).HandlerFunc(httpTraceHdrs(server.WalkHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodWalk).HandlerFunc(httpTraceHdrs(server.WalkHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTDirPath, storageRESTMarkerPath, storageRESTRecursive, storageRESTLeafFile)...)
|
Queries(restQueries(storageRESTVolume, storageRESTDirPath, storageRESTMarkerPath, storageRESTRecursive, storageRESTLeafFile)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDeleteFile).HandlerFunc(httpTraceHdrs(server.DeleteFileHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodDeleteFile).HandlerFunc(httpTraceHdrs(server.DeleteFileHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodDeleteFileBulk).HandlerFunc(httpTraceHdrs(server.DeleteFileBulkHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodDeleteFileBulk).HandlerFunc(httpTraceHdrs(server.DeleteFileBulkHandler)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath)...)
|
||||||
|
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodRenameFile).HandlerFunc(httpTraceHdrs(server.RenameFileHandler)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodRenameFile).HandlerFunc(httpTraceHdrs(server.RenameFileHandler)).
|
||||||
Queries(restQueries(storageRESTSrcVolume, storageRESTSrcPath, storageRESTDstVolume, storageRESTDstPath)...)
|
Queries(restQueries(storageRESTSrcVolume, storageRESTSrcPath, storageRESTDstVolume, storageRESTDstPath)...)
|
||||||
subrouter.Methods(http.MethodPost).Path(SlashSeparator + storageRESTMethodVerifyFile).HandlerFunc(httpTraceHdrs(server.VerifyFile)).
|
subrouter.Methods(http.MethodPost).Path(storageRESTVersionPrefix + storageRESTMethodVerifyFile).HandlerFunc(httpTraceHdrs(server.VerifyFile)).
|
||||||
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTBitrotAlgo, storageRESTBitrotHash, storageRESTLength, storageRESTShardSize)...)
|
Queries(restQueries(storageRESTVolume, storageRESTFilePath, storageRESTBitrotAlgo, storageRESTBitrotHash, storageRESTLength, storageRESTShardSize)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
router.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(versionMismatchHandler))
|
// If none of the routes match add default error handler routes
|
||||||
|
router.NotFoundHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
|
router.MethodNotAllowedHandler = http.HandlerFunc(httpTraceAll(errorResponseHandler))
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ func TestListOnlineDisks(t *testing.T) {
|
|||||||
// appears in outDatedDisks.
|
// appears in outDatedDisks.
|
||||||
tamperedIndex = index
|
tamperedIndex = index
|
||||||
filePath := pathJoin(xlDisks[index].String(), bucket, object, "part.1")
|
filePath := pathJoin(xlDisks[index].String(), bucket, object, "part.1")
|
||||||
f, err := os.OpenFile(filePath, os.O_WRONLY, 0)
|
f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_SYNC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to open %s: %s\n", filePath, err)
|
t.Fatalf("Failed to open %s: %s\n", filePath, err)
|
||||||
}
|
}
|
||||||
@ -319,7 +319,7 @@ func TestDisksWithAllParts(t *testing.T) {
|
|||||||
for _, info := range partsMetadata[diskIndex].Erasure.Checksums {
|
for _, info := range partsMetadata[diskIndex].Erasure.Checksums {
|
||||||
if info.Name == partName {
|
if info.Name == partName {
|
||||||
filePath := pathJoin(xlDisks[diskIndex].String(), bucket, object, partName)
|
filePath := pathJoin(xlDisks[diskIndex].String(), bucket, object, partName)
|
||||||
f, err := os.OpenFile(filePath, os.O_WRONLY, 0)
|
f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_SYNC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to open %s: %s\n", filePath, err)
|
t.Fatalf("Failed to open %s: %s\n", filePath, err)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user