mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Valery Kharseko
22 hours ago 616d5f6c17161905dc9608029826dbf043a68e39
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#
#
# The contents of this file are subject to the terms of the Common Development and
# Distribution License (the License). You may not use this file except in compliance with the
# License.
#
# You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
# specific language governing permission and limitations under the License.
#
# When distributing Covered Software, include this CDDL Header Notice in each file and include
# the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
# Header, with the fields enclosed by brackets [] replaced by your own identifying
# information: "Portions copyright [year] [name of copyright owner]".
#
# Copyright 2026 3A Systems, LLC.
 
# Settings and helpers of the replication convergence run (#1090), sourced by run.sh. Every
# setting comes from the environment, so that the same run goes in CI and on a laptop.
 
TOPOLOGY=${TOPOLOGY:-rs534}
# seconds of load
DURATION=${DURATION:-120}
# the most modifications, and adds or deletes, per second the load sends to each directory
# server; a runner that cannot keep up sends fewer, which the summary shows
LOAD_MOD_RATE=${LOAD_MOD_RATE:-423}
LOAD_ADD_RATE=${LOAD_ADD_RATE:-85}
# users the first directory server imports; the others get them from its initialize
SAMPLE_DATA=${SAMPLE_DATA:-2000}
# the heap of every server and every load client. Without a bound each JVM may take a quarter
# of the memory of the host, fourteen of them on a runner of 16 GB, and the one run without it
# lost both its runners (run 38694855431). No container memory limit: one would kill a server
# in the middle of the run where the heap bound only slows it down
SERVER_JAVA_ARGS=${SERVER_JAVA_ARGS:--server -Xmx1g}
CLIENT_JAVA_ARGS=${CLIENT_JAVA_ARGS:--Xmx256m}
# seconds the whole topology is given to come up: the joins take their turns one at a time
UP_TIMEOUT=${UP_TIMEOUT:-3600}
# seconds the topology is given to converge once the load stops
QUIESCE_TIMEOUT=${QUIESCE_TIMEOUT:-900}
# 1: write to one replica only, which the run must report (a self-test of its checks)
INJECT_DIVERGENCE=${INJECT_DIVERGENCE:-0}
# where the summary, the samples, the exports, the differences and a failed run's state go: a
# directory that is new or empty
OUT=${OUT:-$PWD/replication-out}
# 1: leave the servers of a failed run up, to look at them; the next run removes them
KEEP=${KEEP:-0}
 
# awk reads 0.5 as 0 where the locale's decimal separator is a comma, and the checks sum the
# rates the load tools print with a dot
export LC_ALL=C
 
NETWORK=convergence
ROOT_PASSWORD=password
BASE_DN="dc=example,dc=com"
# the monitor of the replication domain of BASE_DN: cn=Replication,cn=monitor holds one per
# replicated suffix (cn=admin data and cn=schema as well), and a server has another server id
# in each of them
MONITOR_DOMAIN="cn=$(echo "$BASE_DN" | tr '=,' '__'),cn=Replication,cn=monitor"
 
case $TOPOLOGY in
  # #534: directory servers without a replication server and replication servers without data.
  # The directory servers come first in REPLICATION_PEERS: the first of them seeds
  rs534)
    DS_NODES="cv-d0 cv-d1 cv-d2 cv-d3"
    RS_ONLY="cv-r0 cv-r1"
    RS_NODES=$RS_ONLY
    ;;
  # every server holds the data and runs a replication server, which most deployments do
  combined)
    DS_NODES="cv-c0 cv-c1 cv-c2 cv-c3"
    RS_ONLY=
    RS_NODES=$DS_NODES
    ;;
  *)
    echo "unknown TOPOLOGY $TOPOLOGY: rs534 or combined" >&2
    exit 2
    ;;
esac
ALL_NODES=$(echo $DS_NODES $RS_ONLY)
PEERS=$(echo $ALL_NODES | tr ' ' ',')
 
cleanup() {
  local n
  # the load clients of a run that failed before it removed them (load.sh)
  docker rm -f $(docker ps -aq --filter "name=^load-") >/dev/null 2>&1 || true
  docker rm -f $ALL_NODES >/dev/null 2>&1 || true
  docker network rm $NETWORK >/dev/null 2>&1 || true
  for n in $ALL_NODES; do
    docker volume rm -f "vol-$n" >/dev/null 2>&1 || true
  done
}
 
# Where the time goes: each phase logs when it starts, and the run ends - failed or not - with
# the phases sorted by their duration
PHASE=
PHASE_START=$SECONDS
PHASE_TIMES=
phase() { # <name>
  [ -z "$PHASE" ] || PHASE_TIMES+="$((SECONDS - PHASE_START)) s  $PHASE"$'\n'
  PHASE=$1
  PHASE_START=$SECONDS
  echo "=== [${SECONDS} s] $PHASE"
}
 
timings() {
  phase "(end)"
  echo "::group::time per phase, longest first"
  sort -rn <<<"${PHASE_TIMES%$'\n'}"
  echo "total: ${SECONDS} s"
  echo "::endgroup::"
}
 
fail() {
  echo "::error::$1"
  false
}
 
wait_until() { # <seconds> <what> <command> [<argument>...]
  local deadline=$((SECONDS + $1)) what=$2 start=$SECONDS
  shift 2
  until "$@"; do
    [ "$SECONDS" -lt "$deadline" ] || fail "timed out waiting until $what"
    sleep 2
  done
  [ $((SECONDS - start)) -lt 20 ] || echo "    [$((SECONDS - start)) s] until $what"
}
 
is_healthy() { # <container>
  [ "$(docker inspect --format='{{.State.Health.Status}}' "$1")" = healthy ]
}
 
# The background join of the image goes on once the container reports itself healthy: it adds
# replication servers to the replication server lists while its peers register
# (repair_replication_servers in join.sh). Ended once no bootstrap script runs any more, as
# docker-test-replication.sh waits for it
bootstrap_ended() { # <container>
  ! docker exec "$1" sh -c "grep -qs -e 'bootstrap/[j]oin\.sh' -e 'bootstrap/[r]eplicate\.sh' /proc/[0-9]*/cmdline"
}
 
ldaps_search() { # <container> <base DN> <scope> <filter> [<attribute>...]
  local container=$1 base=$2 scope=$3 filter=$4
  shift 4
  docker exec "$container" /opt/opendj/bin/ldapsearch --noPropertiesFile --hostname localhost --port 1636 \
    --useSsl --trustAll --bindDN "cn=Directory Manager" --bindPassword "$ROOT_PASSWORD" \
    --baseDN "$base" --searchScope "$scope" "$filter" "$@"
}
 
# cn=config and cn=monitor through the administration connector, which every role has
admin_search() { # <container> <base DN> <scope> <filter> [<attribute>...]
  local container=$1 base=$2 scope=$3 filter=$4
  shift 4
  docker exec "$container" /opt/opendj/bin/ldapsearch --noPropertiesFile --hostname localhost --port 4444 \
    --useSsl --trustAll --bindDN "cn=Directory Manager" --bindPassword "$ROOT_PASSWORD" \
    --baseDN "$base" --searchScope "$scope" "$filter" "$@"
}
 
runs_replication_server() { # <container>
  admin_search "$1" "cn=config" sub "(objectClass=ds-cfg-replication-server)" 1.1 | grep "^dn:" >/dev/null
}