Skip to content

Commit bd0302e

Browse files
committed
Merge branch 'master' into 102-do-not-create-channel-if-folder-does-not-exist
2 parents 24796eb + 44e1f34 commit bd0302e

2 files changed

Lines changed: 141 additions & 27 deletions

File tree

ada/ada

Lines changed: 139 additions & 25 deletions
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.
@@ -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-
14321440
bulk_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+
18631972
to_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
;;

tests/integration_test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ test_ada_mkdir() {
3030
assertEquals "ada returned error code ${result}" 0 ${result} || return
3131
grep "success" "${stdoutF}" >/dev/null
3232
assertTrue "ada could not create the directory" $? || return
33-
get_locality "/${disk_path}/${dirname}/${testdir}/${subdir}"
34-
assertTrue "could not get locality" $?
33+
is_dir "/${disk_path}/${dirname}/${testdir}/${subdir}"
34+
assertTrue "is not a directory" $?
3535
}
3636

3737

0 commit comments

Comments
 (0)