Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
466 changes: 466 additions & 0 deletions .github/scripts/test-edge-ops.py

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions .github/workflows/edge-it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ jobs:

steps:
- uses: actions/checkout@v5
- name: Test Edge ops scripts
run: python3 .github/scripts/test-edge-ops.py
- name: Set up JDK
uses: actions/setup-java@v5
with:
Expand Down Expand Up @@ -89,6 +91,8 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- name: Test Edge ops scripts
run: python .github/scripts/test-edge-ops.py
- name: Test Edge Windows launchers
shell: powershell
run: .github/scripts/test-edge-windows.ps1
1 change: 1 addition & 0 deletions distribution/src/assembly/all.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
<excludes>
<exclude>*ainode.*</exclude>
<exclude>**/*ainode.*</exclude>
<exclude>**/*edge.*</exclude>
</excludes>
<fileMode>0755</fileMode>
</fileSet>
Expand Down
1 change: 1 addition & 0 deletions distribution/src/assembly/datanode.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
<exclude>**/*confignode.*</exclude>
<exclude>**/*all.*</exclude>
<exclude>**/*ainode.*</exclude>
<exclude>**/*edge.*</exclude>
</excludes>
<fileMode>0755</fileMode>
</fileSet>
Expand Down
11 changes: 11 additions & 0 deletions distribution/src/assembly/edge.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@
</excludes>
<fileMode>0755</fileMode>
</fileSet>
<!-- Edge replacements for the standalone node daemon and cleanup tools. -->
<fileSet>
<outputDirectory>tools</outputDirectory>
<directory>${project.basedir}/../scripts/tools</directory>
<includes>
<include>ops/daemon-edge.sh</include>
<include>ops/destroy-edge.sh</include>
<include>windows/ops/destroy-edge.bat</include>
</includes>
<fileMode>0755</fileMode>
</fileSet>
</fileSets>
<files>
<file>
Expand Down
1 change: 1 addition & 0 deletions iotdb-core/datanode/src/assembly/server.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<exclude>**/*confignode.*</exclude>
<exclude>**/*all.*</exclude>
<exclude>**/*ainode.*</exclude>
<exclude>**/*edge.*</exclude>
</excludes>
<fileMode>0755</fileMode>
</fileSet>
Expand Down
9 changes: 6 additions & 3 deletions scripts/sbin/windows/stop-edge.bat
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
@REM under the License.
@REM

setlocal
echo Stopping IoTDB Edge (the merged ConfigNode + DataNode process)
pushd %~dp0\..\..
pushd "%~dp0\..\.."
set "IOTDB_HOME=%cd%"
popd
powershell -NoProfile -Command "$plain='-DIOTDB_HOME=' + $env:IOTDB_HOME; $quoted='-DIOTDB_HOME=' + [char]34 + $env:IOTDB_HOME + [char]34; Get-CimInstance Win32_Process -Filter \"name='java.exe'\" | Where-Object { $line=$_.CommandLine; $sameHome=$line -and ($line.Contains($plain + ' ') -or $line.EndsWith($plain) -or $line.Contains($quoted + ' ') -or $line.EndsWith($quoted)); $sameHome -and $line.Contains('org.apache.iotdb.edge.EdgeNode') } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force; Write-Host ('IoTDB Edge process ' + $_.ProcessId + ' stopped.') }"
pause
powershell -NoProfile -Command "$ErrorActionPreference='Stop'; $plain='-DIOTDB_HOME=' + $env:IOTDB_HOME; $quoted='-DIOTDB_HOME=' + [char]34 + $env:IOTDB_HOME + [char]34; Get-CimInstance Win32_Process -Filter \"name='java.exe'\" | Where-Object { $line=$_.CommandLine; $sameHome=$line -and ($line.Contains($plain + ' ') -or $line.EndsWith($plain) -or $line.Contains($quoted + ' ') -or $line.EndsWith($quoted)); $sameHome -and $line.Contains('org.apache.iotdb.edge.EdgeNode') } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force; Write-Host ('IoTDB Edge process ' + $_.ProcessId + ' stopped.') }"
set "STOP_STATUS=%errorlevel%"
if not "%~1"=="-f" pause
exit /b %STOP_STATUS%
114 changes: 114 additions & 0 deletions scripts/tools/ops/daemon-edge.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

set -e

IOTDB_HOME="${IOTDB_HOME:-$(cd "$(dirname "$0")"/../.. && pwd)}"
IOTDB_HOME="$(cd "$IOTDB_HOME" && pwd -P)"
export IOTDB_HOME
IOTDB_SBIN_HOME="$IOTDB_HOME/sbin"
SYSTEMD_DIR="${SYSTEMD_DIR:-/etc/systemd/system}"

if [ ! -d "$SYSTEMD_DIR" ] || ! command -v systemctl >/dev/null 2>&1; then
echo "Current system can't support systemd."
exit 1
fi

JAVA=java
if [ -n "$JAVA_HOME" ]; then
JAVA="$JAVA_HOME/bin/java"
if [ -x "$JAVA_HOME/bin/amd64/java" ]; then
JAVA="$JAVA_HOME/bin/amd64/java"
fi
fi
if ! "$JAVA" --version >/dev/null 2>&1; then
echo "Java is not available. Please check JAVA_HOME and PATH."
exit 1
fi

if [ ! -x "$IOTDB_SBIN_HOME/start-edge.sh" ] || [ ! -x "$IOTDB_SBIN_HOME/stop-edge.sh" ]; then
echo "Cannot find the executable Edge start/stop scripts in $IOTDB_SBIN_HOME."
exit 1
fi

# Quote environment values and executable paths using systemd's syntax.
systemd_quote() {
local value="$1"
value="${value//\\/\\\\}"
value="${value//\"/\\\"}"
value="${value//%/%%}"
printf '"%s"' "$value"
}

FILE_NAME="$SYSTEMD_DIR/iotdb-edge.service"
cat > "$FILE_NAME" <<EOF
[Unit]
Description=iotdb-edge
Documentation=https://iotdb.apache.org/
After=network.target
StartLimitIntervalSec=600s
StartLimitBurst=3

[Service]
StandardOutput=null
StandardError=null
LimitNOFILE=65536
# start-edge.sh forks the JVM and records its PID before returning.
Type=forking
PIDFile=${IOTDB_HOME//%/%%}/edge.pid
WorkingDirectory=${IOTDB_HOME//%/%%}
User=root
Group=root
Environment=$(systemd_quote "JAVA_HOME=$JAVA_HOME")
Environment=$(systemd_quote "PATH=${JAVA_HOME:+$JAVA_HOME/bin:}$PATH")
Environment=$(systemd_quote "IOTDB_HOME=$IOTDB_HOME")
Environment=$(systemd_quote "IOTDB_CONF=${IOTDB_CONF:-$IOTDB_HOME/conf}")
Environment=$(systemd_quote "IOTDB_DATA_HOME=${IOTDB_DATA_HOME:-$IOTDB_HOME}")
Environment=$(systemd_quote "IOTDB_LOG_DIR=${IOTDB_LOG_DIR:-$IOTDB_HOME/logs}")
ExecStart=$(systemd_quote "$IOTDB_SBIN_HOME/start-edge.sh")
ExecStop=$(systemd_quote "$IOTDB_SBIN_HOME/stop-edge.sh")
Restart=on-failure
SuccessExitStatus=143
RestartSec=5
RestartPreventExitStatus=SIGKILL

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
echo "Daemon service of IoTDB Edge has been successfully registered."
echo
echo "Do you want to execute 'systemctl start iotdb-edge'? y/n (default y)"
read -r START_SERVICE || START_SERVICE=""
if [[ -z "$START_SERVICE" || "$START_SERVICE" =~ ^[Yy]$ ]]; then
# Stop both an existing service and a manually started Edge before starting.
systemctl stop iotdb-edge
"$IOTDB_SBIN_HOME/stop-edge.sh"
systemctl start iotdb-edge
echo "Executed successfully."
fi
echo
echo "Do you want to execute 'systemctl enable iotdb-edge' to start at boot? y/n (default y)"
read -r ADD_STARTUP || ADD_STARTUP=""
if [[ -z "$ADD_STARTUP" || "$ADD_STARTUP" =~ ^[Yy]$ ]]; then
systemctl enable iotdb-edge
echo "Executed successfully."
fi
161 changes: 161 additions & 0 deletions scripts/tools/ops/destroy-edge.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#!/bin/bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

set -e

if [ "$#" -gt 1 ] || { [ "$#" -eq 1 ] && [ "$1" != "-f" ]; }; then
echo "Usage: $0 [-f]"
exit 1
fi
if [ "${1:-}" != "-f" ]; then
read -r -p "Do you want to clean all the data of IoTDB Edge? y/n (default n): " CLEAN_SERVICE || CLEAN_SERVICE=""
if [[ "$CLEAN_SERVICE" != "y" && "$CLEAN_SERVICE" != "Y" ]]; then
echo "Exiting..."
exit 0
fi
fi

IOTDB_HOME="${IOTDB_HOME:-$(cd "$(dirname "$0")"/../.. && pwd)}"
IOTDB_HOME="$(cd "$IOTDB_HOME" && pwd -P)"
export IOTDB_HOME
IOTDB_CONF="${IOTDB_CONF:-$IOTDB_HOME/conf}"
IOTDB_DATA_HOME="${IOTDB_DATA_HOME:-$IOTDB_HOME}"
if [ -d "$IOTDB_DATA_HOME" ]; then
IOTDB_DATA_HOME="$(cd "$IOTDB_DATA_HOME" && pwd -P)"
fi

if [ ! -f "$IOTDB_HOME/sbin/stop-edge.sh" ]; then
echo "Cannot find $IOTDB_HOME/sbin/stop-edge.sh. No data has been removed."
exit 1
fi

# Stop the matching service first so Restart=on-failure cannot race with cleanup.
if command -v systemctl >/dev/null 2>&1 &&
[ "$(systemctl show --property=PIDFile --value iotdb-edge.service 2>/dev/null)" = "$IOTDB_HOME/edge.pid" ]; then
systemctl stop iotdb-edge
fi
bash "$IOTDB_HOME/sbin/stop-edge.sh" -f

if [ -f "$IOTDB_CONF/iotdb-system.properties" ]; then
CN_CONFIG="$IOTDB_CONF/iotdb-system.properties"
DN_CONFIG="$CN_CONFIG"
else
CN_CONFIG="$IOTDB_CONF/iotdb-confignode.properties"
DN_CONFIG="$IOTDB_CONF/iotdb-datanode.properties"
fi

read_property() {
local config="$1" key="$2" fallback="$3"
if [ ! -f "$config" ]; then
printf '%s\n' "$fallback"
return
fi
# Keep spaces and '=' in values; the last active property wins, as in Java.
awk -v key="$key" -v fallback="$fallback" '
{
separator = index($0, "=")
if (!separator) next
name = substr($0, 1, separator - 1)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", name)
if (name == key) {
value = substr($0, separator + 1)
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
}
}
END { print (value == "" ? fallback : value) }
' "$config"
}

CLEAN_PATHS=()
add_paths() {
local directories="$1" base="$2" path protected
local paths=()
IFS=';,' read -r -a paths <<< "$directories"
for path in "${paths[@]}"; do
path="${path#"${path%%[![:space:]]*}"}"
path="${path%"${path##*[![:space:]]}"}"
[ -n "$path" ] || continue
case "$path" in
*://*|OBJECT_STORAGE) continue ;;
/*) ;;
*) path="$base/$path" ;;
esac
# Remove a final symlink itself, not its target. Resolve directory aliases
# before checking them so '..' and symlinked parents cannot hide a root.
while [[ "$path" != / && "$path" == */ ]]; do path="${path%/}"; done
if [ -L "$path" ]; then
path="$(cd -P "$(dirname "$path")" && pwd -P)/$(basename "$path")"
elif [ -d "$path" ]; then
path="$(cd -P "$path" && pwd -P)"
elif [ -e "$path" ]; then
echo "Refusing to remove a non-directory data path: $path"
exit 1
else
continue
fi
if [ "$path" = / ]; then
echo "Refusing to remove the filesystem root."
exit 1
fi
for protected in "$IOTDB_HOME" "$IOTDB_DATA_HOME" "$HOME"; do
case "$protected/" in
"$path/"*)
echo "Refusing to remove a home directory or its parent: $path"
exit 1
;;
esac
done
CLEAN_PATHS+=("$path")
done
}

# The merged process still uses both sets of node directories. Preserve the
# local destroy-all behavior as well as every custom path from the node tools.
add_paths "data" "$IOTDB_HOME"
add_paths "data/datanode" "$IOTDB_DATA_HOME"
for key in cn_system_dir cn_consensus_dir; do
case "$key" in
cn_system_dir) fallback=data/confignode/system ;;
cn_consensus_dir) fallback=data/confignode/consensus ;;
esac
value=$(read_property "$CN_CONFIG" "$key" "$fallback")
add_paths "$value" "$IOTDB_HOME"
done
for key in dn_system_dir dn_data_dirs dn_consensus_dir dn_wal_dirs dn_tracing_dir dn_sync_dir pipe_receiver_file_dirs iot_consensus_v2_receiver_file_dirs sort_tmp_dir; do
case "$key" in
dn_system_dir) fallback=data/datanode/system ;;
dn_data_dirs) fallback=data/datanode/data ;;
dn_consensus_dir) fallback=data/datanode/consensus ;;
dn_wal_dirs) fallback=data/datanode/wal ;;
dn_tracing_dir) fallback=datanode/tracing ;;
dn_sync_dir) fallback=data/datanode/sync ;;
pipe_receiver_file_dirs) fallback=data/datanode/system/pipe/receiver ;;
iot_consensus_v2_receiver_file_dirs) fallback=data/datanode/system/pipe/consensus/receiver ;;
sort_tmp_dir) fallback=data/datanode/tmp ;;
esac
value=$(read_property "$DN_CONFIG" "$key" "$fallback")
add_paths "$value" "$IOTDB_DATA_HOME"
done

# Validate every target before deleting any data, and finish before reporting success.
for path in "${CLEAN_PATHS[@]}"; do
rm -rf -- "$path"
done
echo "IoTDB Edge clean done ..."
Loading
Loading