@@ -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.
@@ -1411,36 +1437,12 @@ delete_path () {
14111437}
14121438
14131439
1414- get_locality () {
1415- local path=" $1 "
1416- locality=" $( (\
1417- $debug && set -x # If --debug is specified, show curl & jq command
1418- curl " ${curl_authorization[@]} " \
1419- " ${curl_options_common[@]} " \
1420- " ${curl_options_post[@]} " \
1421- -X POST " $api /tape/archiveinfo" \
1422- -d " {\" paths\" :[\" /${path} \" ]}" \
1423- ) | jq . | grep locality) "
1424- if [ -z " $locality " ] ; then
1425- return 1
1426- else
1427- return 0
1428- fi
1429- }
1430-
1431-
14321440bulk_request () {
14331441 local activity=" $1 "
14341442 local pathlist=" $2 "
14351443 local recursive=" $3 "
14361444 if [ " $from_file " == false ] ; then
14371445 local filepath=" $2 "
1438- get_locality " $filepath "
1439- error=$?
1440- if [ " $error " == 1 ] ; then
1441- echo 1>&2 " Error: '$filepath ' does not exist."
1442- exit 1
1443- fi
14441446 type=$( pathtype " $filepath " )
14451447 case $type in
14461448 DIR )
@@ -1860,6 +1862,113 @@ get_dcache_versions () {
18601862}
18611863
18621864
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+
18631972to_json () {
18641973 # Analyze metadata and convert it to JSON so we can feed it to "set-xattr"
18651974 #
@@ -2140,7 +2249,8 @@ validate_input() {
21402249 exit 1
21412250 fi
21422251 ;;
2143- whoami | channels | space )
2252+ whoami | channels | space | quota )
2253+ # These commands do not require additional input validation
21442254 ;;
21452255 ' ' )
21462256 echo 1>&2 " ERROR. Please specify a command. See --help for more information."
@@ -2242,6 +2352,7 @@ api_call () {
22422352 -X GET " $api /user" \
22432353 | jq .
22442354 )
2355+ get_quota own
22452356 ;;
22462357 list )
22472358 type=$( pathtype " $path " )
@@ -2784,6 +2895,9 @@ api_call () {
27842895 )
27852896 fi
27862897 ;;
2898+ quota )
2899+ get_quota " $quota_scope "
2900+ ;;
27872901 * )
27882902 echo " Command '$command ' is not implemented (yet)."
27892903 ;;
0 commit comments