From e24d06f56ef43e572720f6b77d470509a8455b04 Mon Sep 17 00:00:00 2001 From: Josh Elser Date: Wed, 11 Jan 2017 11:55:29 -0500 Subject: [PATCH] HBASE-17025 Add shell commands for space quotas --- hbase-shell/src/main/ruby/hbase/quotas.rb | 44 +++++++++++++++++++++ hbase-shell/src/main/ruby/hbase_constants.rb | 1 + .../src/main/ruby/shell/commands/set_quota.rb | 45 +++++++++++++++++++++- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/hbase-shell/src/main/ruby/hbase/quotas.rb b/hbase-shell/src/main/ruby/hbase/quotas.rb index bf2dc63..e6d08fd 100644 --- a/hbase-shell/src/main/ruby/hbase/quotas.rb +++ b/hbase-shell/src/main/ruby/hbase/quotas.rb @@ -24,14 +24,22 @@ java_import org.apache.hadoop.hbase.quotas.ThrottleType java_import org.apache.hadoop.hbase.quotas.QuotaFilter java_import org.apache.hadoop.hbase.quotas.QuotaRetriever java_import org.apache.hadoop.hbase.quotas.QuotaSettingsFactory +java_import org.apache.hadoop.hbase.quotas.SpaceViolationPolicy module HBaseQuotasConstants + # RPC Quota constants GLOBAL_BYPASS = 'GLOBAL_BYPASS' THROTTLE_TYPE = 'THROTTLE_TYPE' THROTTLE = 'THROTTLE' REQUEST = 'REQUEST' WRITE = 'WRITE' READ = 'READ' + # Space quota constants + SPACE = 'SPACE' + NO_INSERTS = 'NO_INSERTS' + NO_WRITES = 'NO_WRITES' + NO_WRITES_COMPACTIONS = 'NO_WRITES_COMPACTIONS' + DISABLE = 'DISABLE' end module Hbase @@ -107,6 +115,42 @@ module Hbase @admin.setQuota(settings) end + def limit_space(args) + raise(ArgumentError, 'Argument should be a Hash') unless args.kind_of?(Hash) + # Let the user provide a raw number + if args[LIMIT].is_a?(Numeric) + limit = args[LIMIT] + else + # Parse a string a 1K, 2G, etc. + limit = _parse_size(args[LIMIT]) + end + # Extract the policy, failing if something bogus was provided + policy = SpaceViolationPolicy.valueOf(args[POLICY]) + # Create a table or namespace quota + if args.key?(TABLE) + settings = QuotaSettingsFactory.limitTableSpace(TableName.valueOf(args.delete(TABLE)), limit, policy) + elsif args.key?(NAMESPACE) + settings = QuotaSettingsFactory.limitNamespaceSpace(args.delete(NAMESPACE), limit, policy) + else + raise(ArgumentError, 'One of TABLE or NAMESPACE must be specified.') + end + # Apply the quota + @admin.setQuota(settings) + end + + def remove_space_limit(args) + raise(ArgumentError, 'Argument should be a Hash') unless args.kind_of?(Hash) + if args.key?(TABLE) + table = TableName.valueOf(args.delete(TABLE)) + settings = QuotaSettingsFactory.removeTableSpaceLimit(table) + elsif args.key?(NAMESPACE) + settings = QuotaSettingsFactory.removeNamespaceSpaceLimit(args.delete(NAMESPACE)) + else + raise(ArgumentError, 'One of TABLE or NAMESPACE must be specified.') + end + @admin.setQuota(settings) + end + def set_global_bypass(bypass, args) raise(ArgumentError, "Arguments should be a Hash") unless args.kind_of?(Hash) diff --git a/hbase-shell/src/main/ruby/hbase_constants.rb b/hbase-shell/src/main/ruby/hbase_constants.rb index c02d5c6..a857403 100644 --- a/hbase-shell/src/main/ruby/hbase_constants.rb +++ b/hbase-shell/src/main/ruby/hbase_constants.rb @@ -81,6 +81,7 @@ module HBaseConstants NAMESPACES = 'NAMESPACES' CONFIG = 'CONFIG' DATA = 'DATA' + POLICY = 'POLICY' # Load constants from hbase java API def self.promote_constants(constants) diff --git a/hbase-shell/src/main/ruby/shell/commands/set_quota.rb b/hbase-shell/src/main/ruby/shell/commands/set_quota.rb index a638b93..06ed0ba 100644 --- a/hbase-shell/src/main/ruby/shell/commands/set_quota.rb +++ b/hbase-shell/src/main/ruby/shell/commands/set_quota.rb @@ -52,6 +52,37 @@ For example: hbase> set_quota TYPE => THROTTLE, THROTTLE_TYPE => WRITE, USER => 'u1', LIMIT => NONE hbase> set_quota USER => 'u1', GLOBAL_BYPASS => true + +TYPE => SPACE +Users can either set a quota on a table or a namespace. The quota is a limit on the target's +size on the FileSystem and some action to take when the target exceeds that limit. The limit +is in bytes and can expressed using standard metric suffixes (B, K, M, G, T, P), defaulting +to bytes if not provided. Different quotas can be applied to one table at the table and namespace +level; table-level quotas take priority over namespace-level quotas. + +There are a limited number of policies to take when a quota is violation, listed in order of +least strict to most strict. + + NO_INSERTS - No new data is allowed to be ingested (e.g. Put, Increment, Append). + NO_WRITES - Same as NO_INSERTS but Deletes are also disallowed. + NO_WRITES_COMPACTIONS - Same as NO_WRITES but compactions are also disallowed. + DISABLE - The table(s) are disabled. + +For example: + + hbase> set_quota TYPE => SPACE, TABLE => 't1', LIMIT => '1G', POLICY => NO_INSERTS + hbase> set_quota TYPE => SPACE, TABLE => 't2', LIMIT => '50G', POLICY => DISABLE + hbase> set_quota TYPE => SPACE, TABLE => 't3', LIMIT => '2T', POLICY => NO_WRITES_COMPACTIONS + hbase> set_quota TYPE => SPACE, NAMESPACE => 'ns1', LIMIT => '50T', POLICY => NO_WRITES + +Space quotas can also be removed via this command. To remove a space quota, provide NONE +for the limit. + +For example: + + hbase> set_quota TYPE => SPACE, TABLE => 't1', LIMIT => NONE + hbase> set_quota TYPE => SPACE, NAMESPACE => 'ns1', LIMIT => NONE + EOF end @@ -66,8 +97,18 @@ EOF else quotas_admin.throttle(args) end - else - raise "Invalid TYPE argument. got " + qtype + when SPACE + if args[LIMIT].eql? NONE + args.delete(LIMIT) + # Table/Namespace argument is verified in remove_space_limit + quotas_admin.remove_space_limit(args) + else + raise(ArgumentError, 'Expected a LIMIT to be provided') unless args.key?(LIMIT) + raise(ArgumentError, 'Expected a POLICY to be provided') unless args.key?(POLICY) + quotas_admin.limit_space(args) + end + else + raise "Invalid TYPE argument. got " + qtype end elsif args.has_key?(GLOBAL_BYPASS) quotas_admin.set_global_bypass(args.delete(GLOBAL_BYPASS), args) -- 2.10.2