Skip to content

Commit 44e1f34

Browse files
authored
Show quota with --whoami and with --quota (#107)
* With --whoami, show user quotas if set. With --whoami, ada will check whether the user has any quota (on their UID and on their main GID). If they have, the disk & tape quotas are shown, including percentages. If the API returns 404 for both UID and GID quota, it means quotas have not been set, so Ada does not show anything. If the API returns other error messages, Ada will show them. I'm thinking of implementing a `ada --quota` command which shows all quotas, not only the user's own. That would be a next commit. * Use bash array to reduce code Added a check if bash is new enough for arrays; if not, a warning is printed * Implemented --quota command * Language: "and/or" instead of "or" * With --quota, show message if there are no quota in scope ``` % ../SpiderScripts/ada/ada --quota own You do not have any quota set on your user ID or primary group ID. (git branch: 104-support-quota) % ../SpiderScripts/ada/ada --quota all Quota: custodial (tape) custodialLimit % replica (disk) replicaLimit % USER:31029 5,124,339,119 1,000,000,000,000,000 0.0% 1,073,742,937 10,000,000,000 10.7% GROUP:31040 5,124,338,950 null - 1,073,742,937 1,000,000,000,000 0.1% GROUP:40304 0 null - 0 1,000,000,000,000,000 0% ```
1 parent d710e34 commit 44e1f34

1 file changed

Lines changed: 139 additions & 1 deletion

File tree

ada/ada

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ usage() {
228228
The pinned (sticky) capacity can be calculated with:
229229
"ada ... | jq '.total - .free - .precious - .removable'"
230230
231+
--quota <all|own>
232+
Shows storage quotas, for tape (custodial) and for disk (replica).
233+
With 'all' (default), shows all quotas.
234+
With 'own', shows only quotas for your own user ID and/or
235+
your primary group ID.
236+
231237
232238
Configuration files:
233239
@@ -670,6 +676,26 @@ get_args() {
670676
esac
671677
shift
672678
;;
679+
--quota )
680+
command='quota'
681+
case $2 in
682+
own | all )
683+
# Quota scope has been specified by user.
684+
quota_scope="$2"
685+
shift
686+
;;
687+
--* | '' )
688+
# Next argument is another option or absent; not a scope.
689+
# Use default scope 'all'
690+
quota_scope=all
691+
;;
692+
* )
693+
echo 1>&2 "ERROR: '$2' is not a valid scope for --quota. Use 'own' or 'all' (default)"
694+
exit 1
695+
;;
696+
esac
697+
shift
698+
;;
673699
--igtf )
674700
# This option requires either 'true' or 'false' as value.
675701
# Any other value is an error.
@@ -1836,6 +1862,113 @@ get_dcache_versions () {
18361862
}
18371863

18381864

1865+
get_quota () {
1866+
local quota_scope="$1"
1867+
case $quota_scope in
1868+
own | '' )
1869+
query_parameter='user=true'
1870+
;;
1871+
all )
1872+
query_parameter='user=false'
1873+
;;
1874+
* )
1875+
echo 1>&2 "ERROR: quota scope is $quota_scope, but should be either 'own' or 'all'."
1876+
exit 1
1877+
;;
1878+
esac
1879+
# Show quotas, for disk and tape, and for user(s) and group(s).
1880+
# We use bash arrays for this. For that, we need a fresh bash.
1881+
if [ "${BASH_VERSINFO[0]}" -lt 4 ] ; then
1882+
echo 1>&2 "Unable to show quota. Get a newer bash version" \
1883+
"('brew install bash') if you need to view quota."
1884+
return 1
1885+
fi
1886+
declare -A quota
1887+
has_quota=false
1888+
# First we collect the user (UID) quota, then the group (GID) quota.
1889+
# After that, we do the handling & processing.
1890+
for quota_type in user group ; do
1891+
# We use curl's "--writeout" to collect the HTTP return code.
1892+
# If the code is 404, it means the user doesn't have this type of quota.
1893+
response=$(curl "${curl_authorization[@]}" \
1894+
"${curl_options_common[@]}" \
1895+
--silent --show-error \
1896+
--write-out "\nHTTP_CODE_%{http_code}" \
1897+
-X GET "$api/quota/${quota_type}?${query_parameter}" 2>&1
1898+
)
1899+
status=$(echo "$response" | grep '^HTTP_CODE') # HTTP return code
1900+
case $status in
1901+
HTTP_CODE_200 )
1902+
# Quota was found! Process it later.
1903+
has_quota=true
1904+
quota[$quota_type]=$(echo "$response" | grep -v '^HTTP_CODE')
1905+
;;
1906+
HTTP_CODE_404 )
1907+
# No quota of this type found.
1908+
quota[$quota_type]=""
1909+
;;
1910+
* )
1911+
# If it's not a 404 but another error message, there is something wrong.
1912+
# So we print the error message and then quit this function.
1913+
echo 1>&2 "Unable to get $quota_type quota."
1914+
echo 1>&2 "$response"
1915+
return 1
1916+
;;
1917+
esac
1918+
done
1919+
# If there's either a user quota or a group quota, we print it.
1920+
# We use tabs as separators and then use column -t to format it in a table.
1921+
if $has_quota ; then
1922+
{
1923+
# Print header
1924+
printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n" \
1925+
"Quota:" "custodial (tape)" "custodialLimit" "%" "replica (disk)" "replicaLimit" "%"
1926+
# Print user & group quota as tab separated values
1927+
for quota_type in user group ; do
1928+
jq -r ' .[] |
1929+
[
1930+
(.type + ":" + (.id|tostring)),
1931+
(.custodial | tostring | gsub("(?<=\\d)(?=(\\d{3})+$)"; ",")),
1932+
(.custodialLimit | tostring | gsub("(?<=\\d)(?=(\\d{3})+$)"; ",")),
1933+
# custodial percentage (avoid division by null or 0)
1934+
(
1935+
if (.custodialLimit // 0) > 0 then
1936+
((.custodial / .custodialLimit * 100) | tostring | capture("^(?<n>-?\\d+(?:\\.\\d)?)") | .n + "%")
1937+
else
1938+
"-"
1939+
end
1940+
),
1941+
(.replica | tostring | gsub("(?<=\\d)(?=(\\d{3})+$)"; ",")),
1942+
(.replicaLimit | tostring | gsub("(?<=\\d)(?=(\\d{3})+$)"; ",")),
1943+
# replica percentage
1944+
(
1945+
if (.replicaLimit // 0) > 0 then
1946+
((.replica / .replicaLimit * 100) | tostring | capture("^(?<n>-?\\d+(?:\\.\\d)?)") | .n + "%")
1947+
else
1948+
"-"
1949+
end
1950+
)
1951+
] | @tsv
1952+
' <<< "${quota[$quota_type]}"
1953+
done
1954+
} | column -t -s $'\t'
1955+
else
1956+
# No quota found. If user ran `ada --quota`, show message.
1957+
# If the user ran `ada --whoami`, we don't need to show a message; it would only be confusing.
1958+
if [ "$command" == "quota" ] ; then
1959+
case $quota_scope in
1960+
own )
1961+
echo 1>&2 "You do not have any quota set on your user ID or primary group ID."
1962+
;;
1963+
all )
1964+
echo 1>&2 "No quota found on this dCache system."
1965+
;;
1966+
esac
1967+
fi
1968+
fi
1969+
}
1970+
1971+
18391972
to_json () {
18401973
# Analyze metadata and convert it to JSON so we can feed it to "set-xattr"
18411974
#
@@ -2109,7 +2242,8 @@ validate_input() {
21092242
exit 1
21102243
fi
21112244
;;
2112-
whoami | channels | space )
2245+
whoami | channels | space | quota )
2246+
# These commands do not require additional input validation
21132247
;;
21142248
'' )
21152249
echo 1>&2 "ERROR. Please specify a command. See --help for more information."
@@ -2211,6 +2345,7 @@ api_call () {
22112345
-X GET "$api/user" \
22122346
| jq .
22132347
)
2348+
get_quota own
22142349
;;
22152350
list )
22162351
type=$(pathtype "$path")
@@ -2753,6 +2888,9 @@ api_call () {
27532888
)
27542889
fi
27552890
;;
2891+
quota )
2892+
get_quota "$quota_scope"
2893+
;;
27562894
* )
27572895
echo "Command '$command' is not implemented (yet)."
27582896
;;

0 commit comments

Comments
 (0)