feat: implement support batch replication (#15554)

This commit is contained in:
Harshavardhana committed 2022-10-05 23:00:43 -07:00
1 parent 4d761fda81
commit 2a13cc28f2
23 files changed
+5617 -172

No files matched your search

-7
View File
@@ -1,14 +1,7 @@
linters-settings: linters-settings:
golint:
min-confidence: 0
gofumpt: gofumpt:
lang-version: "1.18" lang-version: "1.18"
# Choose whether or not to use the extra rules that are disabled
# by default
extra-rules: false
misspell: misspell:
locale: US locale: US
+12 -3
View File
@@ -411,6 +411,7 @@ func (a adminAPIHandlers) MetricsHandler(w http.ResponseWriter, r *http.Request)
} }
} }
} }
jobID := r.Form.Get("by-jobID")
hosts := strings.Split(r.Form.Get("hosts"), ",") hosts := strings.Split(r.Form.Get("hosts"), ",")
byHost := strings.EqualFold(r.Form.Get("by-host"), "true") byHost := strings.EqualFold(r.Form.Get("by-host"), "true")
@@ -432,12 +433,20 @@ func (a adminAPIHandlers) MetricsHandler(w http.ResponseWriter, r *http.Request)
enc := json.NewEncoder(w) enc := json.NewEncoder(w)
for n > 0 { for n > 0 {
var m madmin.RealtimeMetrics var m madmin.RealtimeMetrics
mLocal := collectLocalMetrics(types, hostMap, diskMap) mLocal := collectLocalMetrics(types, collectMetricsOpts{
hosts: hostMap,
disks: diskMap,
jobID: jobID,
})
m.Merge(&mLocal) m.Merge(&mLocal)
// Allow half the interval for collecting remote... // Allow half the interval for collecting remote...
cctx, cancel := context.WithTimeout(ctx, interval/2) cctx, cancel := context.WithTimeout(ctx, interval/2)
mRemote := collectRemoteMetrics(cctx, types, hostMap, diskMap) mRemote := collectRemoteMetrics(cctx, types, collectMetricsOpts{
hosts: hostMap,
disks: diskMap,
jobID: jobID,
})
cancel() cancel()
m.Merge(&mRemote) m.Merge(&mRemote)
if !byHost { if !byHost {
@@ -449,7 +458,7 @@ func (a adminAPIHandlers) MetricsHandler(w http.ResponseWriter, r *http.Request)
m.Final = n <= 1 m.Final = n <= 1
// Marshal API response // Marshal API reesponse
if err := enc.Encode(&m); err != nil { if err := enc.Encode(&m); err != nil {
n = 0 n = 0
} }
+10
View File
@@ -206,6 +206,16 @@ func registerAdminRouter(router *mux.Router, enableConfigOps bool) {
adminRouter.Methods(http.MethodPost).Path(adminVersion+"/replication/diff").HandlerFunc( adminRouter.Methods(http.MethodPost).Path(adminVersion+"/replication/diff").HandlerFunc(
gz(httpTraceHdrs(adminAPI.ReplicationDiffHandler))).Queries("bucket", "{bucket:.*}") gz(httpTraceHdrs(adminAPI.ReplicationDiffHandler))).Queries("bucket", "{bucket:.*}")
// Batch job operations
adminRouter.Methods(http.MethodPost).Path(adminVersion + "/start-job").HandlerFunc(
gz(httpTraceHdrs(adminAPI.StartBatchJob)))
adminRouter.Methods(http.MethodGet).Path(adminVersion + "/list-jobs").HandlerFunc(
gz(httpTraceHdrs(adminAPI.ListBatchJobs)))
adminRouter.Methods(http.MethodGet).Path(adminVersion + "/describe-job").HandlerFunc(
gz(httpTraceHdrs(adminAPI.DescribeBatchJob)))
// Bucket migration operations // Bucket migration operations
// ExportBucketMetaHandler // ExportBucketMetaHandler
adminRouter.Methods(http.MethodGet).Path(adminVersion + "/export-bucket-metadata").HandlerFunc( adminRouter.Methods(http.MethodGet).Path(adminVersion + "/export-bucket-metadata").HandlerFunc(
+8
View File
@@ -263,6 +263,7 @@ const (
ErrAdminNoSuchUser ErrAdminNoSuchUser
ErrAdminNoSuchGroup ErrAdminNoSuchGroup
ErrAdminGroupNotEmpty ErrAdminGroupNotEmpty
ErrAdminNoSuchJob
ErrAdminNoSuchPolicy ErrAdminNoSuchPolicy
ErrAdminInvalidArgument ErrAdminInvalidArgument
ErrAdminInvalidAccessKey ErrAdminInvalidAccessKey
@@ -1226,6 +1227,11 @@ var errorCodes = errorCodeMap{
Description: "The specified group does not exist.", Description: "The specified group does not exist.",
HTTPStatusCode: http.StatusNotFound, HTTPStatusCode: http.StatusNotFound,
}, },
ErrAdminNoSuchJob: {
Code: "XMinioAdminNoSuchJob",
Description: "The specified job does not exist.",
HTTPStatusCode: http.StatusNotFound,
},
ErrAdminGroupNotEmpty: { ErrAdminGroupNotEmpty: {
Code: "XMinioAdminGroupNotEmpty", Code: "XMinioAdminGroupNotEmpty",
Description: "The specified group is not empty - cannot remove it.", Description: "The specified group is not empty - cannot remove it.",
@@ -1923,6 +1929,8 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
apiErr = ErrAdminNoSuchGroup apiErr = ErrAdminNoSuchGroup
case errGroupNotEmpty: case errGroupNotEmpty:
apiErr = ErrAdminGroupNotEmpty apiErr = ErrAdminGroupNotEmpty
case errNoSuchJob:
apiErr = ErrAdminNoSuchJob
case errNoSuchPolicy: case errNoSuchPolicy:
apiErr = ErrAdminNoSuchPolicy apiErr = ErrAdminNoSuchPolicy
case errSignatureMismatch: case errSignatureMismatch:
+127 -126
View File
@@ -179,135 +179,136 @@ func _() {
_ = x[ErrAdminNoSuchUser-168] _ = x[ErrAdminNoSuchUser-168]
_ = x[ErrAdminNoSuchGroup-169] _ = x[ErrAdminNoSuchGroup-169]
_ = x[ErrAdminGroupNotEmpty-170] _ = x[ErrAdminGroupNotEmpty-170]
_ = x[ErrAdminNoSuchPolicy-171] _ = x[ErrAdminNoSuchJob-171]
_ = x[ErrAdminInvalidArgument-172] _ = x[ErrAdminNoSuchPolicy-172]
_ = x[ErrAdminInvalidAccessKey-173] _ = x[ErrAdminInvalidArgument-173]
_ = x[ErrAdminInvalidSecretKey-174] _ = x[ErrAdminInvalidAccessKey-174]
_ = x[ErrAdminConfigNoQuorum-175] _ = x[ErrAdminInvalidSecretKey-175]
_ = x[ErrAdminConfigTooLarge-176] _ = x[ErrAdminConfigNoQuorum-176]
_ = x[ErrAdminConfigBadJSON-177] _ = x[ErrAdminConfigTooLarge-177]
_ = x[ErrAdminNoSuchConfigTarget-178] _ = x[ErrAdminConfigBadJSON-178]
_ = x[ErrAdminConfigEnvOverridden-179] _ = x[ErrAdminNoSuchConfigTarget-179]
_ = x[ErrAdminConfigDuplicateKeys-180] _ = x[ErrAdminConfigEnvOverridden-180]
_ = x[ErrAdminCredentialsMismatch-181] _ = x[ErrAdminConfigDuplicateKeys-181]
_ = x[ErrInsecureClientRequest-182] _ = x[ErrAdminCredentialsMismatch-182]
_ = x[ErrObjectTampered-183] _ = x[ErrInsecureClientRequest-183]
_ = x[ErrSiteReplicationInvalidRequest-184] _ = x[ErrObjectTampered-184]
_ = x[ErrSiteReplicationPeerResp-185] _ = x[ErrSiteReplicationInvalidRequest-185]
_ = x[ErrSiteReplicationBackendIssue-186] _ = x[ErrSiteReplicationPeerResp-186]
_ = x[ErrSiteReplicationServiceAccountError-187] _ = x[ErrSiteReplicationBackendIssue-187]
_ = x[ErrSiteReplicationBucketConfigError-188] _ = x[ErrSiteReplicationServiceAccountError-188]
_ = x[ErrSiteReplicationBucketMetaError-189] _ = x[ErrSiteReplicationBucketConfigError-189]
_ = x[ErrSiteReplicationIAMError-190] _ = x[ErrSiteReplicationBucketMetaError-190]
_ = x[ErrSiteReplicationConfigMissing-191] _ = x[ErrSiteReplicationIAMError-191]
_ = x[ErrAdminBucketQuotaExceeded-192] _ = x[ErrSiteReplicationConfigMissing-192]
_ = x[ErrAdminNoSuchQuotaConfiguration-193] _ = x[ErrAdminBucketQuotaExceeded-193]
_ = x[ErrHealNotImplemented-194] _ = x[ErrAdminNoSuchQuotaConfiguration-194]
_ = x[ErrHealNoSuchProcess-195] _ = x[ErrHealNotImplemented-195]
_ = x[ErrHealInvalidClientToken-196] _ = x[ErrHealNoSuchProcess-196]
_ = x[ErrHealMissingBucket-197] _ = x[ErrHealInvalidClientToken-197]
_ = x[ErrHealAlreadyRunning-198] _ = x[ErrHealMissingBucket-198]
_ = x[ErrHealOverlappingPaths-199] _ = x[ErrHealAlreadyRunning-199]
_ = x[ErrIncorrectContinuationToken-200] _ = x[ErrHealOverlappingPaths-200]
_ = x[ErrEmptyRequestBody-201] _ = x[ErrIncorrectContinuationToken-201]
_ = x[ErrUnsupportedFunction-202] _ = x[ErrEmptyRequestBody-202]
_ = x[ErrInvalidExpressionType-203] _ = x[ErrUnsupportedFunction-203]
_ = x[ErrBusy-204] _ = x[ErrInvalidExpressionType-204]
_ = x[ErrUnauthorizedAccess-205] _ = x[ErrBusy-205]
_ = x[ErrExpressionTooLong-206] _ = x[ErrUnauthorizedAccess-206]
_ = x[ErrIllegalSQLFunctionArgument-207] _ = x[ErrExpressionTooLong-207]
_ = x[ErrInvalidKeyPath-208] _ = x[ErrIllegalSQLFunctionArgument-208]
_ = x[ErrInvalidCompressionFormat-209] _ = x[ErrInvalidKeyPath-209]
_ = x[ErrInvalidFileHeaderInfo-210] _ = x[ErrInvalidCompressionFormat-210]
_ = x[ErrInvalidJSONType-211] _ = x[ErrInvalidFileHeaderInfo-211]
_ = x[ErrInvalidQuoteFields-212] _ = x[ErrInvalidJSONType-212]
_ = x[ErrInvalidRequestParameter-213] _ = x[ErrInvalidQuoteFields-213]
_ = x[ErrInvalidDataType-214] _ = x[ErrInvalidRequestParameter-214]
_ = x[ErrInvalidTextEncoding-215] _ = x[ErrInvalidDataType-215]
_ = x[ErrInvalidDataSource-216] _ = x[ErrInvalidTextEncoding-216]
_ = x[ErrInvalidTableAlias-217] _ = x[ErrInvalidDataSource-217]
_ = x[ErrMissingRequiredParameter-218] _ = x[ErrInvalidTableAlias-218]
_ = x[ErrObjectSerializationConflict-219] _ = x[ErrMissingRequiredParameter-219]
_ = x[ErrUnsupportedSQLOperation-220] _ = x[ErrObjectSerializationConflict-220]
_ = x[ErrUnsupportedSQLStructure-221] _ = x[ErrUnsupportedSQLOperation-221]
_ = x[ErrUnsupportedSyntax-222] _ = x[ErrUnsupportedSQLStructure-222]
_ = x[ErrUnsupportedRangeHeader-223] _ = x[ErrUnsupportedSyntax-223]
_ = x[ErrLexerInvalidChar-224] _ = x[ErrUnsupportedRangeHeader-224]
_ = x[ErrLexerInvalidOperator-225] _ = x[ErrLexerInvalidChar-225]
_ = x[ErrLexerInvalidLiteral-226] _ = x[ErrLexerInvalidOperator-226]
_ = x[ErrLexerInvalidIONLiteral-227] _ = x[ErrLexerInvalidLiteral-227]
_ = x[ErrParseExpectedDatePart-228] _ = x[ErrLexerInvalidIONLiteral-228]
_ = x[ErrParseExpectedKeyword-229] _ = x[ErrParseExpectedDatePart-229]
_ = x[ErrParseExpectedTokenType-230] _ = x[ErrParseExpectedKeyword-230]
_ = x[ErrParseExpected2TokenTypes-231] _ = x[ErrParseExpectedTokenType-231]
_ = x[ErrParseExpectedNumber-232] _ = x[ErrParseExpected2TokenTypes-232]
_ = x[ErrParseExpectedRightParenBuiltinFunctionCall-233] _ = x[ErrParseExpectedNumber-233]
_ = x[ErrParseExpectedTypeName-234] _ = x[ErrParseExpectedRightParenBuiltinFunctionCall-234]
_ = x[ErrParseExpectedWhenClause-235] _ = x[ErrParseExpectedTypeName-235]
_ = x[ErrParseUnsupportedToken-236] _ = x[ErrParseExpectedWhenClause-236]
_ = x[ErrParseUnsupportedLiteralsGroupBy-237] _ = x[ErrParseUnsupportedToken-237]
_ = x[ErrParseExpectedMember-238] _ = x[ErrParseUnsupportedLiteralsGroupBy-238]
_ = x[ErrParseUnsupportedSelect-239] _ = x[ErrParseExpectedMember-239]
_ = x[ErrParseUnsupportedCase-240] _ = x[ErrParseUnsupportedSelect-240]
_ = x[ErrParseUnsupportedCaseClause-241] _ = x[ErrParseUnsupportedCase-241]
_ = x[ErrParseUnsupportedAlias-242] _ = x[ErrParseUnsupportedCaseClause-242]
_ = x[ErrParseUnsupportedSyntax-243] _ = x[ErrParseUnsupportedAlias-243]
_ = x[ErrParseUnknownOperator-244] _ = x[ErrParseUnsupportedSyntax-244]
_ = x[ErrParseMissingIdentAfterAt-245] _ = x[ErrParseUnknownOperator-245]
_ = x[ErrParseUnexpectedOperator-246] _ = x[ErrParseMissingIdentAfterAt-246]
_ = x[ErrParseUnexpectedTerm-247] _ = x[ErrParseUnexpectedOperator-247]
_ = x[ErrParseUnexpectedToken-248] _ = x[ErrParseUnexpectedTerm-248]
_ = x[ErrParseUnexpectedKeyword-249] _ = x[ErrParseUnexpectedToken-249]
_ = x[ErrParseExpectedExpression-250] _ = x[ErrParseUnexpectedKeyword-250]
_ = x[ErrParseExpectedLeftParenAfterCast-251] _ = x[ErrParseExpectedExpression-251]
_ = x[ErrParseExpectedLeftParenValueConstructor-252] _ = x[ErrParseExpectedLeftParenAfterCast-252]
_ = x[ErrParseExpectedLeftParenBuiltinFunctionCall-253] _ = x[ErrParseExpectedLeftParenValueConstructor-253]
_ = x[ErrParseExpectedArgumentDelimiter-254] _ = x[ErrParseExpectedLeftParenBuiltinFunctionCall-254]
_ = x[ErrParseCastArity-255] _ = x[ErrParseExpectedArgumentDelimiter-255]
_ = x[ErrParseInvalidTypeParam-256] _ = x[ErrParseCastArity-256]
_ = x[ErrParseEmptySelect-257] _ = x[ErrParseInvalidTypeParam-257]
_ = x[ErrParseSelectMissingFrom-258] _ = x[ErrParseEmptySelect-258]
_ = x[ErrParseExpectedIdentForGroupName-259] _ = x[ErrParseSelectMissingFrom-259]
_ = x[ErrParseExpectedIdentForAlias-260] _ = x[ErrParseExpectedIdentForGroupName-260]
_ = x[ErrParseUnsupportedCallWithStar-261] _ = x[ErrParseExpectedIdentForAlias-261]
_ = x[ErrParseNonUnaryAgregateFunctionCall-262] _ = x[ErrParseUnsupportedCallWithStar-262]
_ = x[ErrParseMalformedJoin-263] _ = x[ErrParseNonUnaryAgregateFunctionCall-263]
_ = x[ErrParseExpectedIdentForAt-264] _ = x[ErrParseMalformedJoin-264]
_ = x[ErrParseAsteriskIsNotAloneInSelectList-265] _ = x[ErrParseExpectedIdentForAt-265]
_ = x[ErrParseCannotMixSqbAndWildcardInSelectList-266] _ = x[ErrParseAsteriskIsNotAloneInSelectList-266]
_ = x[ErrParseInvalidContextForWildcardInSelectList-267] _ = x[ErrParseCannotMixSqbAndWildcardInSelectList-267]
_ = x[ErrIncorrectSQLFunctionArgumentType-268] _ = x[ErrParseInvalidContextForWildcardInSelectList-268]
_ = x[ErrValueParseFailure-269] _ = x[ErrIncorrectSQLFunctionArgumentType-269]
_ = x[ErrEvaluatorInvalidArguments-270] _ = x[ErrValueParseFailure-270]
_ = x[ErrIntegerOverflow-271] _ = x[ErrEvaluatorInvalidArguments-271]
_ = x[ErrLikeInvalidInputs-272] _ = x[ErrIntegerOverflow-272]
_ = x[ErrCastFailed-273] _ = x[ErrLikeInvalidInputs-273]
_ = x[ErrInvalidCast-274] _ = x[ErrCastFailed-274]
_ = x[ErrEvaluatorInvalidTimestampFormatPattern-275] _ = x[ErrInvalidCast-275]
_ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbolForParsing-276] _ = x[ErrEvaluatorInvalidTimestampFormatPattern-276]
_ = x[ErrEvaluatorTimestampFormatPatternDuplicateFields-277] _ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbolForParsing-277]
_ = x[ErrEvaluatorTimestampFormatPatternHourClockAmPmMismatch-278] _ = x[ErrEvaluatorTimestampFormatPatternDuplicateFields-278]
_ = x[ErrEvaluatorUnterminatedTimestampFormatPatternToken-279] _ = x[ErrEvaluatorTimestampFormatPatternHourClockAmPmMismatch-279]
_ = x[ErrEvaluatorInvalidTimestampFormatPatternToken-280] _ = x[ErrEvaluatorUnterminatedTimestampFormatPatternToken-280]
_ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbol-281] _ = x[ErrEvaluatorInvalidTimestampFormatPatternToken-281]
_ = x[ErrEvaluatorBindingDoesNotExist-282] _ = x[ErrEvaluatorInvalidTimestampFormatPatternSymbol-282]
_ = x[ErrMissingHeaders-283] _ = x[ErrEvaluatorBindingDoesNotExist-283]
_ = x[ErrInvalidColumnIndex-284] _ = x[ErrMissingHeaders-284]
_ = x[ErrAdminConfigNotificationTargetsFailed-285] _ = x[ErrInvalidColumnIndex-285]
_ = x[ErrAdminProfilerNotEnabled-286] _ = x[ErrAdminConfigNotificationTargetsFailed-286]
_ = x[ErrInvalidDecompressedSize-287] _ = x[ErrAdminProfilerNotEnabled-287]
_ = x[ErrAddUserInvalidArgument-288] _ = x[ErrInvalidDecompressedSize-288]
_ = x[ErrAdminResourceInvalidArgument-289] _ = x[ErrAddUserInvalidArgument-289]
_ = x[ErrAdminAccountNotEligible-290] _ = x[ErrAdminResourceInvalidArgument-290]
_ = x[ErrAccountNotEligible-291] _ = x[ErrAdminAccountNotEligible-291]
_ = x[ErrAdminServiceAccountNotFound-292] _ = x[ErrAccountNotEligible-292]
_ = x[ErrPostPolicyConditionInvalidFormat-293] _ = x[ErrAdminServiceAccountNotFound-293]
_ = x[ErrInvalidChecksum-294] _ = x[ErrPostPolicyConditionInvalidFormat-294]
_ = x[ErrInvalidChecksum-295]
} }
const _APIErrorCode_name = "NoneAccessDeniedBadDigestEntityTooSmallEntityTooLargePolicyTooLargeIncompleteBodyInternalErrorInvalidAccessKeyIDAccessKeyDisabledInvalidBucketNameInvalidDigestInvalidRangeInvalidRangePartNumberInvalidCopyPartRangeInvalidCopyPartRangeSourceInvalidMaxKeysInvalidEncodingMethodInvalidMaxUploadsInvalidMaxPartsInvalidPartNumberMarkerInvalidPartNumberInvalidRequestBodyInvalidCopySourceInvalidMetadataDirectiveInvalidCopyDestInvalidPolicyDocumentInvalidObjectStateMalformedXMLMissingContentLengthMissingContentMD5MissingRequestBodyErrorMissingSecurityHeaderNoSuchBucketNoSuchBucketPolicyNoSuchBucketLifecycleNoSuchLifecycleConfigurationInvalidLifecycleWithObjectLockNoSuchBucketSSEConfigNoSuchCORSConfigurationNoSuchWebsiteConfigurationReplicationConfigurationNotFoundErrorRemoteDestinationNotFoundErrorReplicationDestinationMissingLockRemoteTargetNotFoundErrorReplicationRemoteConnectionErrorReplicationBandwidthLimitErrorBucketRemoteIdenticalToSourceBucketRemoteAlreadyExistsBucketRemoteLabelInUseBucketRemoteArnTypeInvalidBucketRemoteArnInvalidBucketRemoteRemoveDisallowedRemoteTargetNotVersionedErrorReplicationSourceNotVersionedErrorReplicationNeedsVersioningErrorReplicationBucketNeedsVersioningErrorReplicationDenyEditErrorReplicationNoExistingObjectsObjectRestoreAlreadyInProgressNoSuchKeyNoSuchUploadInvalidVersionIDNoSuchVersionNotImplementedPreconditionFailedRequestTimeTooSkewedSignatureDoesNotMatchMethodNotAllowedInvalidPartInvalidPartOrderAuthorizationHeaderMalformedMalformedPOSTRequestPOSTFileRequiredSignatureVersionNotSupportedBucketNotEmptyAllAccessDisabledMalformedPolicyMissingFieldsMissingCredTagCredMalformedInvalidRegionInvalidServiceS3InvalidServiceSTSInvalidRequestVersionMissingSignTagMissingSignHeadersTagMalformedDateMalformedPresignedDateMalformedCredentialDateMalformedCredentialRegionMalformedExpiresNegativeExpiresAuthHeaderEmptyExpiredPresignRequestRequestNotReadyYetUnsignedHeadersMissingDateHeaderInvalidQuerySignatureAlgoInvalidQueryParamsBucketAlreadyOwnedByYouInvalidDurationBucketAlreadyExistsTooManyBucketsMetadataTooLargeUnsupportedMetadataMaximumExpiresSlowDownInvalidPrefixMarkerBadRequestKeyTooLongErrorInvalidBucketObjectLockConfigurationObjectLockConfigurationNotFoundObjectLockConfigurationNotAllowedNoSuchObjectLockConfigurationObjectLockedInvalidRetentionDatePastObjectLockRetainDateUnknownWORMModeDirectiveBucketTaggingNotFoundObjectLockInvalidHeadersInvalidTagDirectiveInvalidEncryptionMethodInvalidEncryptionKeyIDInsecureSSECustomerRequestSSEMultipartEncryptedSSEEncryptedObjectInvalidEncryptionParametersInvalidSSECustomerAlgorithmInvalidSSECustomerKeyMissingSSECustomerKeyMissingSSECustomerKeyMD5SSECustomerKeyMD5MismatchInvalidSSECustomerParametersIncompatibleEncryptionMethodKMSNotConfiguredKMSKeyNotFoundExceptionNoAccessKeyInvalidTokenEventNotificationARNNotificationRegionNotificationOverlappingFilterNotificationFilterNameInvalidFilterNamePrefixFilterNameSuffixFilterValueInvalidOverlappingConfigsUnsupportedNotificationContentSHA256MismatchContentChecksumMismatchReadQuorumWriteQuorumStorageFullRequestBodyParseObjectExistsAsDirectoryInvalidObjectNameInvalidObjectNamePrefixSlashInvalidResourceNameServerNotInitializedOperationTimedOutClientDisconnectedOperationMaxedOutInvalidRequestTransitionStorageClassNotFoundErrorInvalidStorageClassBackendDownMalformedJSONAdminNoSuchUserAdminNoSuchGroupAdminGroupNotEmptyAdminNoSuchPolicyAdminInvalidArgumentAdminInvalidAccessKeyAdminInvalidSecretKeyAdminConfigNoQuorumAdminConfigTooLargeAdminConfigBadJSONAdminNoSuchConfigTargetAdminConfigEnvOverriddenAdminConfigDuplicateKeysAdminCredentialsMismatchInsecureClientRequestObjectTamperedSiteReplicationInvalidRequestSiteReplicationPeerRespSiteReplicationBackendIssueSiteReplicationServiceAccountErrorSiteReplicationBucketConfigErrorSiteReplicationBucketMetaErrorSiteReplicationIAMErrorSiteReplicationConfigMissingAdminBucketQuotaExceededAdminNoSuchQuotaConfigurationHealNotImplementedHealNoSuchProcessHealInvalidClientTokenHealMissingBucketHealAlreadyRunningHealOverlappingPathsIncorrectContinuationTokenEmptyRequestBodyUnsupportedFunctionInvalidExpressionTypeBusyUnauthorizedAccessExpressionTooLongIllegalSQLFunctionArgumentInvalidKeyPathInvalidCompressionFormatInvalidFileHeaderInfoInvalidJSONTypeInvalidQuoteFieldsInvalidRequestParameterInvalidDataTypeInvalidTextEncodingInvalidDataSourceInvalidTableAliasMissingRequiredParameterObjectSerializationConflictUnsupportedSQLOperationUnsupportedSQLStructureUnsupportedSyntaxUnsupportedRangeHeaderLexerInvalidCharLexerInvalidOperatorLexerInvalidLiteralLexerInvalidIONLiteralParseExpectedDatePartParseExpectedKeywordParseExpectedTokenTypeParseExpected2TokenTypesParseExpectedNumberParseExpectedRightParenBuiltinFunctionCallParseExpectedTypeNameParseExpectedWhenClauseParseUnsupportedTokenParseUnsupportedLiteralsGroupByParseExpectedMemberParseUnsupportedSelectParseUnsupportedCaseParseUnsupportedCaseClauseParseUnsupportedAliasParseUnsupportedSyntaxParseUnknownOperatorParseMissLine truncated const _APIErrorCode_name = "NoneAccessDeniedBadDigestEntityTooSmallEntityTooLargePolicyTooLargeIncompleteBodyInternalErrorInvalidAccessKeyIDAccessKeyDisabledInvalidBucketNameInvalidDigestInvalidRangeInvalidRangePartNumberInvalidCopyPartRangeInvalidCopyPartRangeSourceInvalidMaxKeysInvalidEncodingMethodInvalidMaxUploadsInvalidMaxPartsInvalidPartNumberMarkerInvalidPartNumberInvalidRequestBodyInvalidCopySourceInvalidMetadataDirectiveInvalidCopyDestInvalidPolicyDocumentInvalidObjectStateMalformedXMLMissingContentLengthMissingContentMD5MissingRequestBodyErrorMissingSecurityHeaderNoSuchBucketNoSuchBucketPolicyNoSuchBucketLifecycleNoSuchLifecycleConfigurationInvalidLifecycleWithObjectLockNoSuchBucketSSEConfigNoSuchCORSConfigurationNoSuchWebsiteConfigurationReplicationConfigurationNotFoundErrorRemoteDestinationNotFoundErrorReplicationDestinationMissingLockRemoteTargetNotFoundErrorReplicationRemoteConnectionErrorReplicationBandwidthLimitErrorBucketRemoteIdenticalToSourceBucketRemoteAlreadyExistsBucketRemoteLabelInUseBucketRemoteArnTypeInvalidBucketRemoteArnInvalidBucketRemoteRemoveDisallowedRemoteTargetNotVersionedErrorReplicationSourceNotVersionedErrorReplicationNeedsVersioningErrorReplicationBucketNeedsVersioningErrorReplicationDenyEditErrorReplicationNoExistingObjectsObjectRestoreAlreadyInProgressNoSuchKeyNoSuchUploadInvalidVersionIDNoSuchVersionNotImplementedPreconditionFailedRequestTimeTooSkewedSignatureDoesNotMatchMethodNotAllowedInvalidPartInvalidPartOrderAuthorizationHeaderMalformedMalformedPOSTRequestPOSTFileRequiredSignatureVersionNotSupportedBucketNotEmptyAllAccessDisabledMalformedPolicyMissingFieldsMissingCredTagCredMalformedInvalidRegionInvalidServiceS3InvalidServiceSTSInvalidRequestVersionMissingSignTagMissingSignHeadersTagMalformedDateMalformedPresignedDateMalformedCredentialDateMalformedCredentialRegionMalformedExpiresNegativeExpiresAuthHeaderEmptyExpiredPresignRequestRequestNotReadyYetUnsignedHeadersMissingDateHeaderInvalidQuerySignatureAlgoInvalidQueryParamsBucketAlreadyOwnedByYouInvalidDurationBucketAlreadyExistsTooManyBucketsMetadataTooLargeUnsupportedMetadataMaximumExpiresSlowDownInvalidPrefixMarkerBadRequestKeyTooLongErrorInvalidBucketObjectLockConfigurationObjectLockConfigurationNotFoundObjectLockConfigurationNotAllowedNoSuchObjectLockConfigurationObjectLockedInvalidRetentionDatePastObjectLockRetainDateUnknownWORMModeDirectiveBucketTaggingNotFoundObjectLockInvalidHeadersInvalidTagDirectiveInvalidEncryptionMethodInvalidEncryptionKeyIDInsecureSSECustomerRequestSSEMultipartEncryptedSSEEncryptedObjectInvalidEncryptionParametersInvalidSSECustomerAlgorithmInvalidSSECustomerKeyMissingSSECustomerKeyMissingSSECustomerKeyMD5SSECustomerKeyMD5MismatchInvalidSSECustomerParametersIncompatibleEncryptionMethodKMSNotConfiguredKMSKeyNotFoundExceptionNoAccessKeyInvalidTokenEventNotificationARNNotificationRegionNotificationOverlappingFilterNotificationFilterNameInvalidFilterNamePrefixFilterNameSuffixFilterValueInvalidOverlappingConfigsUnsupportedNotificationContentSHA256MismatchContentChecksumMismatchReadQuorumWriteQuorumStorageFullRequestBodyParseObjectExistsAsDirectoryInvalidObjectNameInvalidObjectNamePrefixSlashInvalidResourceNameServerNotInitializedOperationTimedOutClientDisconnectedOperationMaxedOutInvalidRequestTransitionStorageClassNotFoundErrorInvalidStorageClassBackendDownMalformedJSONAdminNoSuchUserAdminNoSuchGroupAdminGroupNotEmptyAdminNoSuchJobAdminNoSuchPolicyAdminInvalidArgumentAdminInvalidAccessKeyAdminInvalidSecretKeyAdminConfigNoQuorumAdminConfigTooLargeAdminConfigBadJSONAdminNoSuchConfigTargetAdminConfigEnvOverriddenAdminConfigDuplicateKeysAdminCredentialsMismatchInsecureClientRequestObjectTamperedSiteReplicationInvalidRequestSiteReplicationPeerRespSiteReplicationBackendIssueSiteReplicationServiceAccountErrorSiteReplicationBucketConfigErrorSiteReplicationBucketMetaErrorSiteReplicationIAMErrorSiteReplicationConfigMissingAdminBucketQuotaExceededAdminNoSuchQuotaConfigurationHealNotImplementedHealNoSuchProcessHealInvalidClientTokenHealMissingBucketHealAlreadyRunningHealOverlappingPathsIncorrectContinuationTokenEmptyRequestBodyUnsupportedFunctionInvalidExpressionTypeBusyUnauthorizedAccessExpressionTooLongIllegalSQLFunctionArgumentInvalidKeyPathInvalidCompressionFormatInvalidFileHeaderInfoInvalidJSONTypeInvalidQuoteFieldsInvalidRequestParameterInvalidDataTypeInvalidTextEncodingInvalidDataSourceInvalidTableAliasMissingRequiredParameterObjectSerializationConflictUnsupportedSQLOperationUnsupportedSQLStructureUnsupportedSyntaxUnsupportedRangeHeaderLexerInvalidCharLexerInvalidOperatorLexerInvalidLiteralLexerInvalidIONLiteralParseExpectedDatePartParseExpectedKeywordParseExpectedTokenTypeParseExpected2TokenTypesParseExpectedNumberParseExpectedRightParenBuiltinFunctionCallParseExpectedTypeNameParseExpectedWhenClauseParseUnsupportedTokenParseUnsupportedLiteralsGroupByParseExpectedMemberParseUnsupportedSelectParseUnsupportedCaseParseUnsupportedCaseClauseParseUnsupportedAliasParseUnsupportedSyntaxParseUnknownOpeLine truncated
var _APIErrorCode_index = [...]uint16{0, 4, 16, 25, 39, 53, 67, 81, 94, 112, 129, 146, 159, 171, 193, 213, 239, 253, 274, 291, 306, 329, 346, 364, 381, 405, 420, 441, 459, 471, 491, 508, 531, 552, 564, 582, 603, 631, 661, 682, 705, 731, 768, 798, 831, 856, 888, 918, 947, 972, 994, 1020, 1042, 1070, 1099, 1133, 1164, 1201, 1225, 1253, 1283, 1292, 1304, 1320, 1333, 1347, 1365, 1385, 1406, 1422, 1433, 1449, 1477, 1497, 1513, 1541, 1555, 1572, 1587, 1600, 1614, 1627, 1640, 1656, 1673, 1694, 1708, 1729, 1742, 1764, 1787, 1812, 1828, 1843, 1858, 1879, 1897, 1912, 1929, 1954, 1972, 1995, 2010, 2029, 2043, 2059, 2078, 2092, 2100, 2119, 2129, 2144, 2180, 2211, 2244, 2273, 2285, 2305, 2329, 2353, 2374, 2398, 2417, 2440, 2462, 2488, 2509, 2527, 2554, 2581, 2602, 2623, 2647, 2672, 2700, 2728, 2744, 2767, 2778, 2790, 2807, 2822, 2840, 2869, 2886, 2902, 2918, 2936, 2954, 2977, 2998, 3021, 3031, 3042, 3053, 3069, 3092, 3109, 3137, 3156, 3176, 3193, 3211, 3228, 3242, 3277, 3296, 3307, 3320, 3335, 3351, 3369, 3386, 3406, 3427, 3448, 3467, 3486, 3504, 3527, 3551, 3575, 3599, 3620, 3634, 3663, 3686, 3713, 3747, 3779, 3809, 3832, 3860, 3884, 3913, 3931, 3948, 3970, 3987, 4005, 4025, 4051, 4067, 4086, 4107, 4111, 4129, 4146, 4172, 4186, 4210, 4231, 4246, 4264, 4287, 4302, 4321, 4338, 4355, 4379, 4406, 4429, 4452, 4469, 4491, 4507, 4527, 4546, 4568, 4589, 4609, 4631, 4655, 4674, 4716, 4737, 4760, 4781, 4812, 4831, 4853, 4873, 4899, 4920, 4942, 4962, 4986, 5009, 5028, 5048, 5070, 5093, 5124, 5162, 5203, 5233, 5247, 5268, 5284, 5306, 5336, 5362, 5390, 5423, 5441, 5464, 5499, 5539, 5581, 5613, 5630, 5655, 5670, 5687, 5697, 5708, 5746, 5800, 5846, 5898, 5946, 5989, 6033, 6061, 6075, 6093, 6129, 6152, 6175, 6197, 6225, 6248, 6266, 6293, 6325, 6340} var _APIErrorCode_index = [...]uint16{0, 4, 16, 25, 39, 53, 67, 81, 94, 112, 129, 146, 159, 171, 193, 213, 239, 253, 274, 291, 306, 329, 346, 364, 381, 405, 420, 441, 459, 471, 491, 508, 531, 552, 564, 582, 603, 631, 661, 682, 705, 731, 768, 798, 831, 856, 888, 918, 947, 972, 994, 1020, 1042, 1070, 1099, 1133, 1164, 1201, 1225, 1253, 1283, 1292, 1304, 1320, 1333, 1347, 1365, 1385, 1406, 1422, 1433, 1449, 1477, 1497, 1513, 1541, 1555, 1572, 1587, 1600, 1614, 1627, 1640, 1656, 1673, 1694, 1708, 1729, 1742, 1764, 1787, 1812, 1828, 1843, 1858, 1879, 1897, 1912, 1929, 1954, 1972, 1995, 2010, 2029, 2043, 2059, 2078, 2092, 2100, 2119, 2129, 2144, 2180, 2211, 2244, 2273, 2285, 2305, 2329, 2353, 2374, 2398, 2417, 2440, 2462, 2488, 2509, 2527, 2554, 2581, 2602, 2623, 2647, 2672, 2700, 2728, 2744, 2767, 2778, 2790, 2807, 2822, 2840, 2869, 2886, 2902, 2918, 2936, 2954, 2977, 2998, 3021, 3031, 3042, 3053, 3069, 3092, 3109, 3137, 3156, 3176, 3193, 3211, 3228, 3242, 3277, 3296, 3307, 3320, 3335, 3351, 3369, 3383, 3400, 3420, 3441, 3462, 3481, 3500, 3518, 3541, 3565, 3589, 3613, 3634, 3648, 3677, 3700, 3727, 3761, 3793, 3823, 3846, 3874, 3898, 3927, 3945, 3962, 3984, 4001, 4019, 4039, 4065, 4081, 4100, 4121, 4125, 4143, 4160, 4186, 4200, 4224, 4245, 4260, 4278, 4301, 4316, 4335, 4352, 4369, 4393, 4420, 4443, 4466, 4483, 4505, 4521, 4541, 4560, 4582, 4603, 4623, 4645, 4669, 4688, 4730, 4751, 4774, 4795, 4826, 4845, 4867, 4887, 4913, 4934, 4956, 4976, 5000, 5023, 5042, 5062, 5084, 5107, 5138, 5176, 5217, 5247, 5261, 5282, 5298, 5320, 5350, 5376, 5404, 5437, 5455, 5478, 5513, 5553, 5595, 5627, 5644, 5669, 5684, 5701, 5711, 5722, 5760, 5814, 5860, 5912, 5960, 6003, 6047, 6075, 6089, 6107, 6143, 6166, 6189, 6211, 6239, 6262, 6280, 6307, 6339, 6354}
func (i APIErrorCode) String() string { func (i APIErrorCode) String() string {
if i < 0 || i >= APIErrorCode(len(_APIErrorCode_index)-1) { if i < 0 || i >= APIErrorCode(len(_APIErrorCode_index)-1) {
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+23
View File
@@ -0,0 +1,23 @@
// Code generated by "stringer -type=batchReplicationMetric -trimprefix=batchReplicationMetric batch-handlers.go"; DO NOT EDIT.
package cmd
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[batchReplicationMetricObject-0]
}
const _batchReplicationMetric_name = "Object"
var _batchReplicationMetric_index = [...]uint8{0, 6}
func (i batchReplicationMetric) String() string {
if i >= batchReplicationMetric(len(_batchReplicationMetric_index)-1) {
return "batchReplicationMetric(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _batchReplicationMetric_name[_batchReplicationMetric_index[i]:_batchReplicationMetric_index[i+1]]
}
+12 -2
View File
@@ -1875,12 +1875,22 @@ func (z *erasureServerPools) Walk(ctx context.Context, bucket, prefix string, re
versionsSorter(fivs.Versions).reverse() versionsSorter(fivs.Versions).reverse()
for _, version := range fivs.Versions { for _, version := range fivs.Versions {
send := true
if opts.WalkFilter != nil && !opts.WalkFilter(version) {
send = false
}
if !send {
continue
}
versioned := vcfg != nil && vcfg.Versioned(version.Name) versioned := vcfg != nil && vcfg.Versioned(version.Name)
objInfo := version.ToObjectInfo(bucket, version.Name, versioned)
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
case results <- version.ToObjectInfo(bucket, version.Name, versioned): case results <- objInfo:
} }
} }
} }
@@ -1904,7 +1914,7 @@ func (z *erasureServerPools) Walk(ctx context.Context, bucket, prefix string, re
path: path, path: path,
filterPrefix: filterPrefix, filterPrefix: filterPrefix,
recursive: true, recursive: true,
forwardTo: "", forwardTo: opts.WalkMarker,
minDisks: 1, minDisks: 1,
reportNotFound: false, reportNotFound: false,
agreed: loadEntry, agreed: loadEntry,
+12 -2
View File
@@ -3050,12 +3050,22 @@ func (es *erasureSingle) Walk(ctx context.Context, bucket, prefix string, result
versionsSorter(fivs.Versions).reverse() versionsSorter(fivs.Versions).reverse()
for _, version := range fivs.Versions { for _, version := range fivs.Versions {
send := true
if opts.WalkFilter != nil && !opts.WalkFilter(version) {
send = false
}
if !send {
continue
}
versioned := vcfg != nil && vcfg.Versioned(version.Name) versioned := vcfg != nil && vcfg.Versioned(version.Name)
objInfo := version.ToObjectInfo(bucket, version.Name, versioned)
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
case results <- version.ToObjectInfo(bucket, version.Name, versioned): case results <- objInfo:
} }
} }
} }
@@ -3079,7 +3089,7 @@ func (es *erasureSingle) Walk(ctx context.Context, bucket, prefix string, result
path: path, path: path,
filterPrefix: filterPrefix, filterPrefix: filterPrefix,
recursive: true, recursive: true,
forwardTo: "", forwardTo: opts.WalkMarker,
minDisks: 1, minDisks: 1,
reportNotFound: false, reportNotFound: false,
agreed: loadEntry, agreed: loadEntry,
+17 -7
View File
@@ -25,23 +25,29 @@ import (
"github.com/minio/minio/internal/disk" "github.com/minio/minio/internal/disk"
) )
func collectLocalMetrics(types madmin.MetricType, hosts map[string]struct{}, disks map[string]struct{}) (m madmin.RealtimeMetrics) { type collectMetricsOpts struct {
hosts map[string]struct{}
disks map[string]struct{}
jobID string
}
func collectLocalMetrics(types madmin.MetricType, opts collectMetricsOpts) (m madmin.RealtimeMetrics) {
if types == madmin.MetricsNone { if types == madmin.MetricsNone {
return return
} }
if len(hosts) > 0 { if len(opts.hosts) > 0 {
if _, ok := hosts[globalMinioAddr]; !ok { if _, ok := opts.hosts[globalMinioAddr]; !ok {
return return
} }
} }
if types.Contains(madmin.MetricsDisk) && !globalIsGateway { if types.Contains(madmin.MetricsDisk) {
m.ByDisk = make(map[string]madmin.DiskMetric) m.ByDisk = make(map[string]madmin.DiskMetric)
aggr := madmin.DiskMetric{ aggr := madmin.DiskMetric{
CollectedAt: time.Now(), CollectedAt: time.Now(),
} }
for name, disk := range collectLocalDisksMetrics(disks) { for name, disk := range collectLocalDisksMetrics(opts.disks) {
m.ByDisk[name] = disk m.ByDisk[name] = disk
aggr.Merge(&disk) aggr.Merge(&disk)
} }
@@ -56,6 +62,10 @@ func collectLocalMetrics(types madmin.MetricType, hosts map[string]struct{}, dis
metrics := globalOSMetrics.report() metrics := globalOSMetrics.report()
m.Aggregated.OS = &metrics m.Aggregated.OS = &metrics
} }
if types.Contains(madmin.MetricsBatchJobs) {
m.Aggregated.BatchJobs = globalBatchJobsMetrics.report(opts.jobID)
}
// Add types... // Add types...
// ByHost is a shallow reference, so careful about sharing. // ByHost is a shallow reference, so careful about sharing.
@@ -143,11 +153,11 @@ func collectLocalDisksMetrics(disks map[string]struct{}) map[string]madmin.DiskM
return metrics return metrics
} }
func collectRemoteMetrics(ctx context.Context, types madmin.MetricType, hosts map[string]struct{}, disks map[string]struct{}) (m madmin.RealtimeMetrics) { func collectRemoteMetrics(ctx context.Context, types madmin.MetricType, opts collectMetricsOpts) (m madmin.RealtimeMetrics) {
if !globalIsDistErasure { if !globalIsDistErasure {
return return
} }
all := globalNotificationSys.GetMetrics(ctx, types, hosts, disks) all := globalNotificationSys.GetMetrics(ctx, types, opts)
for _, remote := range all { for _, remote := range all {
m.Merge(&remote) m.Merge(&remote)
} }
+4 -4
View File
@@ -731,7 +731,7 @@ func (sys *NotificationSys) GetOSInfo(ctx context.Context) []madmin.OSInfo {
} }
// GetMetrics - Get metrics from all peers. // GetMetrics - Get metrics from all peers.
func (sys *NotificationSys) GetMetrics(ctx context.Context, t madmin.MetricType, hosts map[string]struct{}, disks map[string]struct{}) []madmin.RealtimeMetrics { func (sys *NotificationSys) GetMetrics(ctx context.Context, t madmin.MetricType, opts collectMetricsOpts) []madmin.RealtimeMetrics {
reply := make([]madmin.RealtimeMetrics, len(sys.peerClients)) reply := make([]madmin.RealtimeMetrics, len(sys.peerClients))
g := errgroup.WithNErrs(len(sys.peerClients)) g := errgroup.WithNErrs(len(sys.peerClients))
@@ -740,8 +740,8 @@ func (sys *NotificationSys) GetMetrics(ctx context.Context, t madmin.MetricType,
continue continue
} }
host := client.host.String() host := client.host.String()
if len(hosts) > 0 { if len(opts.hosts) > 0 {
if _, ok := hosts[host]; !ok { if _, ok := opts.hosts[host]; !ok {
continue continue
} }
} }
@@ -749,7 +749,7 @@ func (sys *NotificationSys) GetMetrics(ctx context.Context, t madmin.MetricType,
index := index index := index
g.Go(func() error { g.Go(func() error {
var err error var err error
reply[index], err = sys.peerClients[index].GetMetrics(ctx, t, disks) reply[index], err = sys.peerClients[index].GetMetrics(ctx, t, opts)
return err return err
}, index) }, index)
} }
+2
View File
@@ -85,6 +85,8 @@ type ObjectOptions struct {
// mainly set for certain WRITE operations. // mainly set for certain WRITE operations.
SkipDecommissioned bool SkipDecommissioned bool
WalkFilter func(info FileInfo) bool // return WalkFilter returns 'true/false'
WalkMarker string // set to skip until this object
PrefixEnabledFn func(prefix string) bool // function which returns true if versioning is enabled on prefix PrefixEnabledFn func(prefix string) bool // function which returns true if versioning is enabled on prefix
// IndexCB will return any index created but the compression. // IndexCB will return any index created but the compression.
+4 -3
View File
@@ -195,12 +195,13 @@ func (client *peerRESTClient) GetMemInfo(ctx context.Context) (info madmin.MemIn
} }
// GetMetrics - fetch metrics from a remote node. // GetMetrics - fetch metrics from a remote node.
func (client *peerRESTClient) GetMetrics(ctx context.Context, t madmin.MetricType, diskMap map[string]struct{}) (info madmin.RealtimeMetrics, err error) { func (client *peerRESTClient) GetMetrics(ctx context.Context, t madmin.MetricType, opts collectMetricsOpts) (info madmin.RealtimeMetrics, err error) {
values := make(url.Values) values := make(url.Values)
values.Set(peerRESTTypes, strconv.FormatUint(uint64(t), 10)) values.Set(peerRESTMetricsTypes, strconv.FormatUint(uint64(t), 10))
for disk := range diskMap { for disk := range opts.disks {
values.Set(peerRESTDisk, disk) values.Set(peerRESTDisk, disk)
} }
values.Set(peerRESTJobID, opts.jobID)
respBody, err := client.callWithContext(ctx, peerRESTMethodMetrics, values, nil, -1) respBody, err := client.callWithContext(ctx, peerRESTMethodMetrics, values, nil, -1)
if err != nil { if err != nil {
return return
+2 -1
View File
@@ -91,8 +91,9 @@ const (
peerRESTConcurrent = "concurrent" peerRESTConcurrent = "concurrent"
peerRESTDuration = "duration" peerRESTDuration = "duration"
peerRESTStorageClass = "storage-class" peerRESTStorageClass = "storage-class"
peerRESTTypes = "types" peerRESTMetricsTypes = "types"
peerRESTDisk = "disk" peerRESTDisk = "disk"
peerRESTJobID = "job-id"
peerRESTListenBucket = "bucket" peerRESTListenBucket = "bucket"
peerRESTListenPrefix = "prefix" peerRESTListenPrefix = "prefix"
+9 -7
View File
@@ -425,23 +425,25 @@ func (s *peerRESTServer) GetMetricsHandler(w http.ResponseWriter, r *http.Reques
} }
var types madmin.MetricType var types madmin.MetricType
if t, _ := strconv.ParseUint(r.Form.Get(peerRESTTypes), 10, 64); t != 0 { if t, _ := strconv.ParseUint(r.Form.Get(peerRESTMetricsTypes), 10, 64); t != 0 {
types = madmin.MetricType(t) types = madmin.MetricType(t)
} else { } else {
types = madmin.MetricsAll types = madmin.MetricsAll
} }
diskMap := make(map[string]struct{}) diskMap := make(map[string]struct{})
if r.Form != nil { for _, disk := range r.Form[peerRESTDisk] {
for _, disk := range r.Form[peerRESTDisk] { diskMap[disk] = struct{}{}
diskMap[disk] = struct{}{}
}
} }
jobID := r.Form.Get(peerRESTJobID)
ctx, cancel := context.WithCancel(r.Context()) ctx, cancel := context.WithCancel(r.Context())
defer cancel() defer cancel()
info := collectLocalMetrics(types, nil, diskMap) info := collectLocalMetrics(types, collectMetricsOpts{
disks: diskMap,
jobID: jobID,
})
logger.LogIf(ctx, gob.NewEncoder(w).Encode(info)) logger.LogIf(ctx, gob.NewEncoder(w).Encode(info))
} }
@@ -1308,7 +1310,7 @@ func registerPeerRESTHandlers(router *mux.Router) {
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodServerInfo).HandlerFunc(httpTraceHdrs(server.ServerInfoHandler))
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodProcInfo).HandlerFunc(httpTraceHdrs(server.GetProcInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodProcInfo).HandlerFunc(httpTraceHdrs(server.GetProcInfoHandler))
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMemInfo).HandlerFunc(httpTraceHdrs(server.GetMemInfoHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMemInfo).HandlerFunc(httpTraceHdrs(server.GetMemInfoHandler))
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMetrics).HandlerFunc(httpTraceHdrs(server.GetMetricsHandler)).Queries(restQueries(peerRESTTypes)...) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodMetrics).HandlerFunc(httpTraceHdrs(server.GetMetricsHandler)).Queries(restQueries(peerRESTMetricsTypes)...)
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysErrors).HandlerFunc(httpTraceHdrs(server.GetSysErrorsHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysErrors).HandlerFunc(httpTraceHdrs(server.GetSysErrorsHandler))
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysServices).HandlerFunc(httpTraceHdrs(server.GetSysServicesHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysServices).HandlerFunc(httpTraceHdrs(server.GetSysServicesHandler))
subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysConfig).HandlerFunc(httpTraceHdrs(server.GetSysConfigHandler)) subrouter.Methods(http.MethodPost).Path(peerRESTVersionPrefix + peerRESTMethodSysConfig).HandlerFunc(httpTraceHdrs(server.GetSysConfigHandler))
+2
View File
@@ -601,6 +601,8 @@ func serverMain(ctx *cli.Context) {
initBackgroundReplication(GlobalContext, newObject) initBackgroundReplication(GlobalContext, newObject)
initBackgroundTransition(GlobalContext, newObject) initBackgroundTransition(GlobalContext, newObject)
globalBatchJobPool = newBatchJobPool(GlobalContext, newObject, 100)
go func() { go func() {
err := globalTierConfigMgr.Init(GlobalContext, newObject) err := globalTierConfigMgr.Init(GlobalContext, newObject)
if err != nil { if err != nil {
+2 -2
View File
@@ -45,8 +45,8 @@ func oldLinux() bool {
func setMaxResources() (err error) { func setMaxResources() (err error) {
// Set the Go runtime max threads threshold to 90% of kernel setting. // Set the Go runtime max threads threshold to 90% of kernel setting.
sysMaxThreads, mErr := sys.GetMaxThreads() sysMaxThreads, err := sys.GetMaxThreads()
if mErr == nil { if err == nil {
minioMaxThreads := (sysMaxThreads * 90) / 100 minioMaxThreads := (sysMaxThreads * 90) / 100
// Only set max threads if it is greater than the default one // Only set max threads if it is greater than the default one
if minioMaxThreads > 10000 { if minioMaxThreads > 10000 {
+152
View File
@@ -0,0 +1,152 @@
# MinIO Batch Job
MinIO Batch jobs is an MinIO object management feature that lets you manage objects at scale. Jobs currently supported by MinIO
- Replicate objects between buckets on multiple sites
Upcoming Jobs
- Copy objects from NAS to MinIO
- Copy objects from HDFS to MinIO
## Replication Job
To perform replication via batch jobs, you create a job. The job consists of a job description YAML that describes
- Source location from where the objects must be copied from
- Target location from where the objects must be copied to
- Fine grained filtering is available to pick relevant objects from source to copy from
MinIO batch jobs framework also provides
- Retrying a failed job automatically driven by user input
- Monitoring job progress in real-time
- Send notifications upon completion or failure to user configured target
Following YAML describes the structure of a replication job, each value is documented and self-describing.
```yaml
replicate:
apiVersion: v1
# source of the objects to be replicated
source:
type: TYPE # valid values are "minio"
bucket: BUCKET
prefix: PREFIX
# NOTE: if source is remote then target must be "local"
# endpoint: ENDPOINT
# credentials:
# accessKey: ACCESS-KEY
# secretKey: SECRET-KEY
# sessionToken: SESSION-TOKEN # Available when rotating credentials are used
# target where the objects must be replicated
target:
type: TYPE # valid values are "minio"
bucket: BUCKET
prefix: PREFIX
# NOTE: if target is remote then source must be "local"
# endpoint: ENDPOINT
# credentials:
# accessKey: ACCESS-KEY
# secretKey: SECRET-KEY
# sessionToken: SESSION-TOKEN # Available when rotating credentials are used
# optional flags based filtering criteria
# for all source objects
flags:
filter:
newerThan: "7d" # match objects newer than this value (e.g. 7d10h31s)
olderThan: "7d" # match objects older than this value (e.g. 7d10h31s)
createdAfter: "date" # match objects created after "date"
createdBefore: "date" # match objects created before "date"
## NOTE: tags are not supported when "source" is remote.
# tags:
# - key: "name"
# value: "pick*" # match objects with tag 'name', with all values starting with 'pick'
## NOTE: metadata filter not supported when "source" is non MinIO.
# metadata:
# - key: "content-type"
# value: "image/*" # match objects with 'content-type', with all values starting with 'image/'
notify:
endpoint: "https://notify.endpoint" # notification endpoint to receive job status events
token: "Bearer xxxxx" # optional authentication token for the notification endpoint
retry:
attempts: 10 # number of retries for the job before giving up
delay: "500ms" # least amount of delay between each retry
```
You can create and run multiple 'replication' jobs at a time there are no predefined limits set.
## Batch Jobs Terminology
### Job
A job is the basic unit of work for MinIO Batch Job. A job is a self describing YAML, once this YAML is submitted and evaluated - MinIO performs the requested actions on each of the objects obtained under the described criteria in job YAML file.
### Type
Type describes the job type, such as replicating objects between MinIO sites. Each job performs a single type of operation across all objects that match the job description criteria.
## Batch Jobs via Commandline
[mc](http://github.com/minio/mc) provides 'mc batch' command to create, start and manage submitted jobs.
```
NAME:
mc batch - manage batch jobs
USAGE:
mc batch COMMAND [COMMAND FLAGS | -h] [ARGUMENTS...]
COMMANDS:
generate generate a new batch job definition
start start a new batch job
list, ls list all current batch jobs
status summarize job events on MinIO server in real-time
describe describe job definition for a job
```
### Generate a job yaml
```
mc batch generate alias/ replicate
```
### Start the batch job (returns back the JID)
```
mc batch start alias/ ./replicate.yaml
Successfully start 'replicate' job `E24HH4nNMcgY5taynaPfxu` on '2022-09-26 17:19:06.296974771 -0700 PDT'
```
### List all batch jobs
```
mc batch list alias/
ID TYPE USER STARTED
E24HH4nNMcgY5taynaPfxu replicate minioadmin 1 minute ago
```
### List all 'replicate' batch jobs
```
mc batch list alias/ --type replicate
ID TYPE USER STARTED
E24HH4nNMcgY5taynaPfxu replicate minioadmin 1 minute ago
```
### Real-time 'status' for a batch job
```
mc batch status myminio/ E24HH4nNMcgY5taynaPfxu
●∙∙
Objects: 28766
Versions: 28766
Throughput: 3.0 MiB/s
Transferred: 406 MiB
Elapsed: 2m14.227222868s
CurrObjName: share/doc/xml-core/examples/foo.xmlcatalogs
```
### 'describe' the batch job yaml.
```
mc batch describe myminio/ E24HH4nNMcgY5taynaPfxu
replicate:
apiVersion: v1
...
```
+3 -2
View File
@@ -40,6 +40,7 @@ require (
github.com/klauspost/readahead v1.4.0 github.com/klauspost/readahead v1.4.0
github.com/klauspost/reedsolomon v1.11.0 github.com/klauspost/reedsolomon v1.11.0
github.com/lib/pq v1.10.7 github.com/lib/pq v1.10.7
github.com/lithammer/shortuuid/v4 v4.0.0
github.com/miekg/dns v1.1.50 github.com/miekg/dns v1.1.50
github.com/minio/cli v1.24.0 github.com/minio/cli v1.24.0
github.com/minio/console v0.20.6-0.20221003060434-413870e995a9 github.com/minio/console v0.20.6-0.20221003060434-413870e995a9
@@ -74,7 +75,7 @@ require (
github.com/secure-io/sio-go v0.3.1 github.com/secure-io/sio-go v0.3.1
github.com/shirou/gopsutil/v3 v3.22.8 github.com/shirou/gopsutil/v3 v3.22.8
github.com/streadway/amqp v1.0.0 github.com/streadway/amqp v1.0.0
github.com/tinylib/msgp v1.1.7-0.20211026165309-e818a1881b0e github.com/tinylib/msgp v1.1.7-0.20220719154719-f3635b96e483
github.com/valyala/bytebufferpool v1.0.0 github.com/valyala/bytebufferpool v1.0.0
github.com/xdg/scram v1.0.5 github.com/xdg/scram v1.0.5
github.com/yargevad/filepathx v1.0.0 github.com/yargevad/filepathx v1.0.0
@@ -88,6 +89,7 @@ require (
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9
google.golang.org/api v0.96.0 google.golang.org/api v0.96.0
gopkg.in/yaml.v2 v2.4.0
) )
require ( require (
@@ -222,6 +224,5 @@ require (
gopkg.in/h2non/filetype.v1 v1.0.5 // indirect gopkg.in/h2non/filetype.v1 v1.0.5 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
+4 -2
View File
@@ -584,6 +584,8 @@ github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCi
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c=
github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
@@ -899,8 +901,8 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tinylib/msgp v1.1.3/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.3/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
github.com/tinylib/msgp v1.1.7-0.20211026165309-e818a1881b0e h1:P5tyWbssToKowBPTA1/EzqPXwrZNc8ZeNPdjgpcDEoI= github.com/tinylib/msgp v1.1.7-0.20220719154719-f3635b96e483 h1:dV39KLgsNZGri7Hn5QhHwRQzGf7kHOki2vZujFXDFhI=
github.com/tinylib/msgp v1.1.7-0.20211026165309-e818a1881b0e/go.mod h1:g7jEyb18KPe65d9RRhGw+ThaJr5duyBH8eaFgBUor7Y= github.com/tinylib/msgp v1.1.7-0.20220719154719-f3635b96e483/go.mod h1:g7jEyb18KPe65d9RRhGw+ThaJr5duyBH8eaFgBUor7Y=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
+4 -4
View File
@@ -94,10 +94,10 @@ const (
// Credentials holds access and secret keys. // Credentials holds access and secret keys.
type Credentials struct { type Credentials struct {
AccessKey string `xml:"AccessKeyId" json:"accessKey,omitempty"` AccessKey string `xml:"AccessKeyId" json:"accessKey,omitempty" yaml:"accessKey"`
SecretKey string `xml:"SecretAccessKey" json:"secretKey,omitempty"` SecretKey string `xml:"SecretAccessKey" json:"secretKey,omitempty" yaml:"secretKey"`
Expiration time.Time `xml:"Expiration" json:"expiration,omitempty"` SessionToken string `xml:"SessionToken" json:"sessionToken,omitempty" yaml:"sessionToken"`
SessionToken string `xml:"SessionToken" json:"sessionToken,omitempty"` Expiration time.Time `xml:"Expiration" json:"expiration,omitempty" yaml:"-"`
Status string `xml:"-" json:"status,omitempty"` Status string `xml:"-" json:"status,omitempty"`
ParentUser string `xml:"-" json:"parentUser,omitempty"` ParentUser string `xml:"-" json:"parentUser,omitempty"`
Groups []string `xml:"-" json:"groups,omitempty"` Groups []string `xml:"-" json:"groups,omitempty"`