Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,20 @@ Perform the following steps as a root user on your Edge appliance.

4. Tar the MongoDB data and data lake contents from {{< product-c8y-iot >}} DataHub if present, into */opt/edge-appliance-backup.tar* :

1. Migrate HSQL db.

```shell
pip install https://download.cumulocity.com/Cumulocity-Edge/Installer/2025/cdh_migration-2025-py3-none-any.whl \
&& cdh-migration
```
wait until you see an out put `INFO - Data export complete: database_export.sql`
2.
```shell
tar -zcf /opt/edge-appliance-backup.tar /opt/appliance-edgedb-backup /opt/softwareag /opt/mongodb/cdh-dremio/distributed-storage /opt/mongodb/cdh-master/datalake /home/admin/database_export.sql
```

If DataHub is not present:

```shell
tar -zcf /opt/edge-appliance-backup.tar /opt/appliance-edgedb-backup /opt/softwareag
```
Expand Down Expand Up @@ -247,8 +261,78 @@ After installing and configuring Edge 2025, proceed to migrate the data backed u
```shell
rm -rf /opt/appliance-edgedb-backup /opt/edge-appliance-backup.tar
```
### Step 5 - Restore DataHub
1. Stop Edge operator:
```shell
kubectl scale deployment c8yedge-operator-controller-manager -n c8yedge --replicas=0
```

2. Set tenant option `CDH_PASSWORD_SECRET` on edge tenant:
1. Get the secret from backup:
```shell
grep CDH_PASSWORD_SECRET /opt/softwareag/cdh-console/conf/cdh-console-env
```
2. Set tenant option on edge:
```shell
curl --location 'https://<EDGE_HOST_IP>/tenant/options/' \
-H 'Content-Type: application/vnd.com.nsn.cumulocity.option+json' \
-H 'Accept: application/vnd.com.nsn.cumulocity.option+json' \
-u "management/${MANAGEMENT_ADMIN_USER}:${MANAGEMENT_ADMIN_PASSWORD}" \
--data '{
"category": "datahub",
"key": "credentials.CDH_PASSWORD_SECRET",
"value": "<PASSWORD_SECRET_FROM_PREVIOUS_STEP>"
}'
```

3. Migrate dremio:
1. Redeploy dremio in maintanace mode for migration, fetch dremio helm chart from installartifacts:
```shell
kubectl get pv -A -o yaml | grep -A1 installartifacts-backing | awk '/path:/ {print $2}'
```
2. Backup values.yaml:
```shell
helm get values dremio -n c8yedge --all -o yaml > dremio_values.yaml
```
3. Set dremio to maintanance:
```shell
helm upgrade dremio ./dremio-11.0.648.tgz -n c8yedge -f dremio_values.yaml --set DremioAdmin=true --wait
```
4. Restore RocksDB from backup:
```shell
kubectl exec -n c8yedge dremio-admin -- rm -rf /opt/dremio/data/db && kubectl cp /opt/mongodb/cdh-master/data/db dremio-admin:/opt/dremio/data/ -n c8yedge
```
5. Restore datalake contents:
```shell
rm -rf /datahub/distributedStorage/* /datahub/datalake/* && cp -a /opt/mongodb/cdh-dremio/distributed-storage/. /datahub/distributedStorage/ && cp -a /opt/mongodb/cdh-master/datalake/. /datahub/datalake/
```
6. Exit from maintaince mode:
```shell
helm upgrade dremio ./dremio-11.0.648.tgz -n c8yedge -f dremio_values.yaml --set DremioAdmin=false --wait
```

4. Restore DataHub:
```shell
kubectl cp /home/admin/database_export.sql -n c8yedge datahub-mysql-0:/tmp/database_export.sql && \
kubectl exec -i -n c8yedge datahub-mysql-0 -- sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" CDH_edge < /tmp/database_export.sql'
```

5. Configure dremio:
Post migration, dremio will have legacy configuration of c8y_source from appliance, this needs to be updated for dremio to communicate with mongo. In this step we will update the `c8y_source` configuration:
1. Set support property “store.plugin.keep_metadata_on_replace“ = true in Dremio (goto Settings > Support)
2. Configure settings of “c8y-source” as required for edge on K8s:
a. Configure MongoDB host name and credentials
3. Set support property “store.plugin.keep_metadata_on_replace“ = false in Dremio
```shell
curl -sfL {{< link-c8y-doc-baseurl >}}files/edge-k8s/dremio_source_configuration.sh -O && bash ./dremio_source_configuration.sh
```

6. Start Edge operator:
```shell
kubectl scale deployment c8yedge-operator-controller-manager -n c8yedge --replicas=1
```

### Step 5 - Configuring Edge 2025 post migration
### Step 6 - Configuring Edge 2025 post migration
After successfully migrating your data to Edge 2025, you'll need to configure it to match your previous Edge Appliance VM setup. Here's what you need to do:

#### What's already available?
Expand Down
145 changes: 145 additions & 0 deletions static/files/edge-k8s/dremio_source_configuration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/bin/bash
set -euo pipefail
trap 'echo "Error on line $LINENO"; exit 1' ERR

# ------- Configuration (no manual inputs) -------
NAMESPACE="c8yedge"
SOURCE_NAME="c8y_source"
MONGO_SECRET="internal-edge-db-users"
DREMIO_SECRET="dremio-admin-credentials"
MONGO_SVC="edge-db-rs0"
DREMIO_SVC="cumulocity-ontoplb"
DREMIO_PORT=9047

# ------- Fetch Dremio admin credentials -------
DREMIO_USER=$(kubectl get secret -n "$NAMESPACE" "$DREMIO_SECRET" -o jsonpath='{.data.DREMIO_ADMIN_USER}' | base64 -d)
DREMIO_PASS=$(kubectl get secret -n "$NAMESPACE" "$DREMIO_SECRET" -o jsonpath='{.data.DREMIO_ADMIN_PASSWORD}' | base64 -d)

# ------- Resolve Dremio endpoint (LoadBalancer IP or ClusterIP fallback) -------
DREMIO_IP=$(kubectl get svc -n "$NAMESPACE" "$DREMIO_SVC" -o jsonpath='{.status.loadBalancer.ingress[0].ip}' 2>/dev/null || true)
if [[ -z "$DREMIO_IP" || "$DREMIO_IP" == "null" ]]; then
DREMIO_IP=$(kubectl get svc -n "$NAMESPACE" "$DREMIO_SVC" -o jsonpath='{.spec.clusterIP}')
fi
if [[ -z "$DREMIO_IP" ]]; then
echo "Failed to locate Dremio service IP for $DREMIO_SVC in namespace $NAMESPACE"
exit 1
fi
DREMIO_URL="https://${DREMIO_IP}:${DREMIO_PORT}"

# ------- Login to Dremio and build Authorization header -------
LOGIN_JSON=$(curl -sk -X POST "$DREMIO_URL/apiv2/login" \
-H "Content-Type: application/json" \
-d "{\"userName\":\"$DREMIO_USER\",\"password\":\"$DREMIO_PASS\"}")

AUTH_TOKEN=$(echo "$LOGIN_JSON" | jq -r '.token')
if [[ -z "$AUTH_TOKEN" || "$AUTH_TOKEN" == "null" ]]; then
echo "Failed to obtain Dremio auth token. Response:"
echo "$LOGIN_JSON" | jq .
exit 1
fi
AUTH_HEADER="_dremio${AUTH_TOKEN}"

# ------- Fetch Mongo credentials -------
MONGO_USER=$(kubectl get secret -n "$NAMESPACE" "$MONGO_SECRET" -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_USER}' | base64 -d)
MONGO_PASS=$(kubectl get secret -n "$NAMESPACE" "$MONGO_SECRET" -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}' | base64 -d)

# ------- Resolve Mongo service host and port -------
MONGO_HOSTNAME=$(kubectl get svc -n "$NAMESPACE" "$MONGO_SVC" -o jsonpath='{.metadata.name}' 2>/dev/null || true)
if [[ -z "$MONGO_HOSTNAME" ]]; then
echo "Failed to find MongoDB service $MONGO_SVC in namespace $NAMESPACE"
exit 1
fi
MONGO_PORT=$(kubectl get svc -n "$NAMESPACE" "$MONGO_SVC" -o jsonpath='{.spec.ports[0].port}')
MONGO_FQDN="${MONGO_HOSTNAME}.${NAMESPACE}.svc.cluster.local"

# ------- Fetch existing source JSON from Dremio -------
SOURCE_JSON=$(curl -sk -H "Authorization: ${AUTH_HEADER}" "$DREMIO_URL/apiv2/source/$SOURCE_NAME")
SOURCE_ID=$(echo "$SOURCE_JSON" | jq -r '.id // empty')
SOURCE_TAG=$(echo "$SOURCE_JSON" | jq -r '.tag // empty')

if [[ -z "$SOURCE_ID" ]]; then
echo "Source '$SOURCE_NAME' not found in Dremio at $DREMIO_URL"
exit 1
fi

# ------- Enable keep_metadata_on_replace (true) -------
curl -sk -X PUT "$DREMIO_URL/apiv2/settings/store.plugin.keep_metadata_on_replace" \
-H "Authorization: ${AUTH_HEADER}" \
-H "Content-Type: application/json" \
--data '{"type":"BOOLEAN","id":"store.plugin.keep_metadata_on_replace","value":true}' >/dev/null

# ------- Build minimal update payload based on requested layout -------
# Layout:
# {
# "config": { hostList:[{hostname,port}], useSsl:true, authenticationType, authDatabase, ... }
# }
UPDATE_PAYLOAD=$(jq -n \
--arg id "$SOURCE_ID" \
--arg tag "$SOURCE_TAG" \
--arg name "$SOURCE_NAME" \
--arg type "MONGO" \
--arg host "$MONGO_FQDN" \
--argjson port "$MONGO_PORT" \
--arg user "$MONGO_USER" \
--arg pass "$MONGO_PASS" \
'{
id: $id,
tag: $tag,
type: $type,
name: $name,
config: {
hostList: [{ hostname: $host, port: $port }],
useSsl: true,
authenticationType: "MASTER",
username: $user,
password: $pass,
authDatabase: "admin",
authenticationTimeoutMillis: 2000,
secondaryReadsOnly: false,
subpartitionSize: 0,
sampleSize: 4095,
sampleMethod: "FIRST",
propertyList: [{ name: "maxPoolSize", value: "100" }],
useCaseInsensitiveFieldNames: false
}
}')

# ------- PUT update to Dremio -------
UPDATE_RESPONSE=$(curl -sk -X PUT "$DREMIO_URL/apiv2/source/$SOURCE_NAME/?nocache=$(date +%s)" \
-H "Authorization: ${AUTH_HEADER}" \
-H "Content-Type: application/json" \
--data "$UPDATE_PAYLOAD")

# If Dremio returned an errorMessage, show and exit
if echo "$UPDATE_RESPONSE" | jq -e 'has("errorMessage")' >/dev/null 2>&1; then
echo "Dremio returned error while updating source:"
echo "$UPDATE_RESPONSE" | jq .
# Attempt to restore the keep_metadata flag to false before exiting
curl -sk -X PUT "$DREMIO_URL/apiv2/settings/store.plugin.keep_metadata_on_replace" \
-H "Authorization: ${AUTH_HEADER}" \
-H "Content-Type: application/json" \
--data '{"type":"BOOLEAN","id":"store.plugin.keep_metadata_on_replace","value":false}' >/dev/null || true
exit 1
fi

# ------- Restore keep_metadata_on_replace (false) -------
curl -sk -X PUT "$DREMIO_URL/apiv2/settings/store.plugin.keep_metadata_on_replace" \
-H "Authorization: ${AUTH_HEADER}" \
-H "Content-Type: application/json" \
--data '{"type":"BOOLEAN","id":"store.plugin.keep_metadata_on_replace","value":false}' >/dev/null

# ------- Verify connection/status -------
VERIFY_JSON=$(curl -sk -H "Authorization: ${AUTH_HEADER}" "$DREMIO_URL/apiv2/source/$SOURCE_NAME")
STATUS=$(echo "$VERIFY_JSON" | jq -r '.state.status // empty')
MSG=$(echo "$VERIFY_JSON" | jq -r '.state.messages[0].message // empty')

if [[ "$STATUS" == "good" ]]; then
echo "SUCCESS: Dremio source '$SOURCE_NAME' updated and MongoDB is connected."
echo "Message: $MSG"
exit 0
else
echo "WARNING: Dremio source updated but status is not 'good'."
echo "Status: $STATUS"
echo "Message: $MSG"
exit 2
fi