committed by
GitHub
35 changed files with 754 additions and 101 deletions
@ -1,3 +0,0 @@ |
|||
###### WARNING NOTE: 'localhost' can not be used as CLOUD_RPC_HOST |
|||
|
|||
Please note that your ThingsBoard base URL is **'localhost'** at the moment. **'localhost'** cannot be used for docker containers - please update **CLOUD_RPC_HOST** environment variable below to the IP address of your machine (*docker **host** machine*). IP address must be `192.168.1.XX` or similar format. In other case - ThingsBoard Edge service, that is running in docker container, will not be able to connect to the cloud. |
|||
@ -0,0 +1,15 @@ |
|||
#### Upgrading to ${TB_EDGE_VERSION}EDGE |
|||
|
|||
**ThingsBoard Edge package download:** |
|||
```bash |
|||
wget https://github.com/thingsboard/thingsboard-edge/releases/download/v${TB_EDGE_TAG}/tb-edge-${TB_EDGE_TAG}.rpm |
|||
{:copy-code} |
|||
``` |
|||
##### ThingsBoard Edge service upgrade |
|||
|
|||
Install package: |
|||
```bash |
|||
sudo rpm -Uvh tb-edge-${TB_EDGE_TAG}.rpm |
|||
{:copy-code} |
|||
``` |
|||
${UPGRADE_DB} |
|||
@ -0,0 +1,10 @@ |
|||
#### Upgrading to ${TB_EDGE_VERSION} |
|||
|
|||
Execute the following command to pull **${TB_EDGE_VERSION}** image: |
|||
|
|||
```bash |
|||
docker pull thingsboard/tb-edge:${TB_EDGE_VERSION} |
|||
{:copy-code} |
|||
``` |
|||
|
|||
${UPGRADE_DB} |
|||
@ -0,0 +1,23 @@ |
|||
Modify ‘main’ docker compose (`docker-compose.yml`) file for ThingsBoard Edge and update version of the image: |
|||
```bash |
|||
nano docker-compose.yml |
|||
{:copy-code} |
|||
``` |
|||
|
|||
```text |
|||
version: '3.8' |
|||
services: |
|||
mytbedge: |
|||
restart: always |
|||
image: "thingsboard/tb-edge:${TB_EDGE_VERSION}" |
|||
... |
|||
``` |
|||
|
|||
Make sure your image is the set to **tb-edge-${TB_EDGE_VERSION}**. |
|||
Execute the following commands to up this docker compose directly: |
|||
|
|||
```bash |
|||
docker compose up -d |
|||
docker compose logs -f mytbedge |
|||
{:copy-code} |
|||
``` |
|||
@ -0,0 +1,61 @@ |
|||
Create docker compose file for ThingsBoard Edge upgrade process: |
|||
|
|||
```bash |
|||
> docker-compose-upgrade.yml && nano docker-compose-upgrade.yml |
|||
{:copy-code} |
|||
``` |
|||
|
|||
Add the following lines to the yml file: |
|||
|
|||
```bash |
|||
version: '3.8' |
|||
services: |
|||
mytbedge: |
|||
restart: on-failure |
|||
image: "thingsboard/tb-edge:${TB_EDGE_VERSION}" |
|||
environment: |
|||
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/tb-edge |
|||
volumes: |
|||
- tb-edge-data:/data |
|||
- tb-edge-logs:/var/log/tb-edge |
|||
entrypoint: upgrade-tb-edge.sh |
|||
postgres: |
|||
restart: always |
|||
image: "postgres:15" |
|||
ports: |
|||
- "5432" |
|||
environment: |
|||
POSTGRES_DB: tb-edge |
|||
POSTGRES_PASSWORD: postgres |
|||
volumes: |
|||
- tb-edge-postgres-data:/var/lib/postgresql/data |
|||
|
|||
volumes: |
|||
tb-edge-data: |
|||
name: tb-edge-data |
|||
tb-edge-logs: |
|||
name: tb-edge-logs |
|||
tb-edge-postgres-data: |
|||
name: tb-edge-postgres-data |
|||
{:copy-code} |
|||
``` |
|||
|
|||
Execute the following command to start upgrade process: |
|||
|
|||
```bash |
|||
docker compose -f docker-compose-upgrade.yml up |
|||
{:copy-code} |
|||
``` |
|||
|
|||
Once upgrade process successfully completed, exit from the docker-compose shell by this combination: |
|||
|
|||
```text |
|||
Ctrl + C |
|||
``` |
|||
|
|||
Execute the following command to stop TB Edge upgrade container: |
|||
|
|||
```bash |
|||
docker compose -f docker-compose-upgrade.yml stop |
|||
{:copy-code} |
|||
``` |
|||
@ -0,0 +1,83 @@ |
|||
Here is the list of commands, that can be used to quickly upgrade ThingsBoard Edge on Docker (Linux or MacOS). |
|||
|
|||
#### Prepare for upgrading ThingsBoard Edge |
|||
Set the terminal in the directory which contains the `docker-compose.yml` file and execute the following command |
|||
to stop and remove currently running TB Edge container: |
|||
|
|||
```bash |
|||
docker compose stop |
|||
docker compose rm mytbedge |
|||
{:copy-code} |
|||
``` |
|||
|
|||
**OPTIONAL:** If you still rely on Docker Compose as docker-compose (with a hyphen) here is the list of the above commands: |
|||
```text |
|||
docker-compose stop |
|||
docker-compose rm mytbedge |
|||
``` |
|||
|
|||
##### Migrating Data from Docker Bind Mount Folders to Docker Volumes |
|||
Starting with the **3.6.2** release, the ThingsBoard team has transitioned from using Docker bind mount folders to Docker volumes. |
|||
This change aims to enhance security and efficiency in storing data for Docker containers and to mitigate permission issues across various environments. |
|||
|
|||
To migrate from Docker bind mounts to Docker volumes, please execute the following commands: |
|||
|
|||
```bash |
|||
docker run --rm -v tb-edge-data:/volume -v ~/.mytb-edge-data:/backup busybox sh -c "cp -a /backup/. /volume" |
|||
docker run --rm -v tb-edge-logs:/volume -v ~/.mytb-edge-logs:/backup busybox sh -c "cp -a /backup/. /volume" |
|||
docker run --rm -v tb-edge-postgres-data:/volume -v ~/.mytb-edge-data/db:/backup busybox sh -c "cp -a /backup/. /volume" |
|||
{:copy-code} |
|||
``` |
|||
|
|||
After completing the data migration to the newly created Docker volumes, you'll need to update the volume mounts in your Docker Compose configuration. |
|||
Modify the `docker-compose.yml` file for ThingsBoard Edge to update the volume settings. |
|||
|
|||
First, please update docker compose file version. Find next snippet: |
|||
```text |
|||
version: '3.0' |
|||
... |
|||
``` |
|||
|
|||
And replace it with: |
|||
```text |
|||
version: '3.8' |
|||
... |
|||
``` |
|||
|
|||
Then update volume mounts. Locate the following snippet: |
|||
```text |
|||
volumes: |
|||
- ~/.mytb-edge-data:/data |
|||
- ~/.mytb-edge-logs:/var/log/tb-edge |
|||
... |
|||
``` |
|||
|
|||
And replace it with: |
|||
```text |
|||
volumes: |
|||
- tb-edge-data:/data |
|||
- tb-edge-logs:/var/log/tb-edge |
|||
... |
|||
``` |
|||
|
|||
Apply a similar update for the PostgreSQL service. Find the section: |
|||
```text |
|||
volumes: |
|||
- ~/.mytb-edge-data/db:/var/lib/postgresql/data |
|||
... |
|||
``` |
|||
|
|||
And replace it with: |
|||
```text |
|||
volumes: |
|||
- tb-edge-postgres-data/:/var/lib/postgresql/data |
|||
... |
|||
``` |
|||
|
|||
##### Backup Database |
|||
Make a copy of the database volume before upgrading: |
|||
|
|||
```bash |
|||
docker run --rm -v tb-edge-postgres-data:/source -v tb-edge-postgres-data-backup:/backup busybox sh -c "cp -a /source/. /backup" |
|||
{:copy-code} |
|||
``` |
|||
@ -0,0 +1,6 @@ |
|||
Start the service |
|||
|
|||
```bash |
|||
sudo systemctl tb-edge start |
|||
{:copy-code} |
|||
``` |
|||
@ -0,0 +1,15 @@ |
|||
#### Upgrading to ${TB_EDGE_VERSION}EDGE |
|||
|
|||
**ThingsBoard Edge package download:** |
|||
```bash |
|||
wget https://github.com/thingsboard/thingsboard-edge/releases/download/v${TB_EDGE_TAG}/tb-edge-${TB_EDGE_TAG}.deb |
|||
{:copy-code} |
|||
``` |
|||
##### ThingsBoard Edge service upgrade |
|||
|
|||
Install package: |
|||
```bash |
|||
sudo dpkg -i tb-edge-${TB_EDGE_TAG}.deb |
|||
{:copy-code} |
|||
``` |
|||
${UPGRADE_DB} |
|||
@ -0,0 +1,8 @@ |
|||
**NOTE**: Package installer may ask you to merge your tb-edge configuration. It is preferred to use **merge option** to make sure that all your previous parameters will not be overwritten. |
|||
|
|||
Execute regular upgrade script: |
|||
|
|||
```bash |
|||
sudo /usr/share/tb-edge/bin/install/upgrade.sh --fromVersion=${FROM_TB_EDGE_VERSION} |
|||
{:copy-code} |
|||
``` |
|||
@ -0,0 +1,36 @@ |
|||
Here is the list of commands, that can be used to quickly upgrade ThingsBoard Edge on ${OS} |
|||
|
|||
#### Prepare for upgrading ThingsBoard Edge |
|||
|
|||
Stop ThingsBoard Edge service: |
|||
|
|||
```bash |
|||
sudo systemctl stop tb-edge |
|||
{:copy-code} |
|||
``` |
|||
|
|||
##### Backup Database |
|||
Make a backup of the database before upgrading. **Make sure you have enough space to place a backup of the database.** |
|||
|
|||
Check database size: |
|||
|
|||
```bash |
|||
sudo -u postgres psql -c "SELECT pg_size_pretty( pg_database_size('tb_edge') );" |
|||
{:copy-code} |
|||
``` |
|||
|
|||
Check free space: |
|||
|
|||
```bash |
|||
df -h / |
|||
{:copy-code} |
|||
``` |
|||
|
|||
If there is enough free space - make a backup: |
|||
|
|||
```bash |
|||
sudo -Hiu postgres pg_dump tb_edge > tb_edge.sql.bak |
|||
{:copy-code} |
|||
``` |
|||
|
|||
Check backup file created successfully. |
|||
@ -0,0 +1,158 @@ |
|||
/** |
|||
* Copyright © 2016-2023 The Thingsboard Authors |
|||
* |
|||
* Licensed 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. |
|||
*/ |
|||
package org.thingsboard.server.service.edge.instructions; |
|||
|
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.Setter; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
|||
import org.springframework.stereotype.Service; |
|||
import org.thingsboard.server.common.data.EdgeUpgradeInfo; |
|||
import org.thingsboard.server.common.data.edge.EdgeInstructions; |
|||
import org.thingsboard.server.queue.util.TbCoreComponent; |
|||
import org.thingsboard.server.service.install.InstallScripts; |
|||
|
|||
import java.io.IOException; |
|||
import java.nio.file.Files; |
|||
import java.nio.file.Path; |
|||
import java.nio.file.Paths; |
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
@Service |
|||
@Slf4j |
|||
@RequiredArgsConstructor |
|||
@ConditionalOnProperty(prefix = "edges", value = "enabled", havingValue = "true") |
|||
@TbCoreComponent |
|||
public class DefaultEdgeUpgradeInstructionsService implements EdgeUpgradeInstructionsService { |
|||
|
|||
private static final Map<String, EdgeUpgradeInfo> upgradeVersionHashMap = new HashMap<>(); |
|||
|
|||
private static final String EDGE_DIR = "edge"; |
|||
private static final String INSTRUCTIONS_DIR = "instructions"; |
|||
private static final String UPGRADE_DIR = "upgrade"; |
|||
|
|||
private final InstallScripts installScripts; |
|||
|
|||
@Value("${app.version:unknown}") |
|||
@Setter |
|||
private String appVersion; |
|||
|
|||
@Override |
|||
public EdgeInstructions getUpgradeInstructions(String edgeVersion, String upgradeMethod) { |
|||
String tbVersion = appVersion.replace("-SNAPSHOT", ""); |
|||
String currentEdgeVersion = convertEdgeVersionToDocsFormat(edgeVersion); |
|||
switch (upgradeMethod.toLowerCase()) { |
|||
case "docker": |
|||
return getDockerUpgradeInstructions(tbVersion, currentEdgeVersion); |
|||
case "ubuntu": |
|||
case "centos": |
|||
return getLinuxUpgradeInstructions(tbVersion, currentEdgeVersion, upgradeMethod.toLowerCase()); |
|||
default: |
|||
throw new IllegalArgumentException("Unsupported upgrade method for Edge: " + upgradeMethod); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void updateInstructionMap(Map<String, EdgeUpgradeInfo> map) { |
|||
for (String key : map.keySet()) { |
|||
upgradeVersionHashMap.put(key, map.get(key)); |
|||
} |
|||
} |
|||
|
|||
private EdgeInstructions getDockerUpgradeInstructions(String tbVersion, String currentEdgeVersion) { |
|||
EdgeUpgradeInfo edgeUpgradeInfo = upgradeVersionHashMap.get(currentEdgeVersion); |
|||
if (edgeUpgradeInfo == null || edgeUpgradeInfo.getNextEdgeVersion() == null || tbVersion.equals(currentEdgeVersion)) { |
|||
return new EdgeInstructions("Edge upgrade instruction for " + currentEdgeVersion + "EDGE is not available."); |
|||
} |
|||
StringBuilder result = new StringBuilder(readFile(resolveFile("docker", "upgrade_preparing.md"))); |
|||
while (edgeUpgradeInfo.getNextEdgeVersion() != null || !tbVersion.equals(currentEdgeVersion)) { |
|||
String edgeVersion = edgeUpgradeInfo.getNextEdgeVersion(); |
|||
String dockerUpgradeInstructions = readFile(resolveFile("docker", "instructions.md")); |
|||
if (edgeUpgradeInfo.isRequiresUpdateDb()) { |
|||
String upgradeDb = readFile(resolveFile("docker", "upgrade_db.md")); |
|||
dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${UPGRADE_DB}", upgradeDb); |
|||
} else { |
|||
dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${UPGRADE_DB}", ""); |
|||
} |
|||
dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${TB_EDGE_VERSION}", edgeVersion + "EDGE"); |
|||
dockerUpgradeInstructions = dockerUpgradeInstructions.replace("${FROM_TB_EDGE_VERSION}", currentEdgeVersion + "EDGE"); |
|||
currentEdgeVersion = edgeVersion; |
|||
edgeUpgradeInfo = upgradeVersionHashMap.get(edgeUpgradeInfo.getNextEdgeVersion()); |
|||
result.append(dockerUpgradeInstructions); |
|||
} |
|||
String startService = readFile(resolveFile("docker", "start_service.md")); |
|||
startService = startService.replace("${TB_EDGE_VERSION}", currentEdgeVersion + "EDGE"); |
|||
result.append(startService); |
|||
return new EdgeInstructions(result.toString()); |
|||
} |
|||
|
|||
private EdgeInstructions getLinuxUpgradeInstructions(String tbVersion, String currentEdgeVersion, String os) { |
|||
EdgeUpgradeInfo edgeUpgradeInfo = upgradeVersionHashMap.get(currentEdgeVersion); |
|||
if (edgeUpgradeInfo == null || edgeUpgradeInfo.getNextEdgeVersion() == null || tbVersion.equals(currentEdgeVersion)) { |
|||
return new EdgeInstructions("Edge upgrade instruction for " + currentEdgeVersion + "EDGE is not available."); |
|||
} |
|||
String upgrade_preparing = readFile(resolveFile("upgrade_preparing.md")); |
|||
upgrade_preparing = upgrade_preparing.replace("${OS}", os.equals("centos") ? "RHEL/CentOS 7/8" : "Ubuntu"); |
|||
StringBuilder result = new StringBuilder(upgrade_preparing); |
|||
while (edgeUpgradeInfo.getNextEdgeVersion() != null || !tbVersion.equals(currentEdgeVersion)) { |
|||
String edgeVersion = edgeUpgradeInfo.getNextEdgeVersion(); |
|||
String linuxUpgradeInstructions = readFile(resolveFile(os, "instructions.md")); |
|||
if (edgeUpgradeInfo.isRequiresUpdateDb()) { |
|||
String upgradeDb = readFile(resolveFile("upgrade_db.md")); |
|||
linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${UPGRADE_DB}", upgradeDb); |
|||
} else { |
|||
linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${UPGRADE_DB}", ""); |
|||
} |
|||
linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${TB_EDGE_TAG}", getTagVersion(edgeVersion)); |
|||
linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${FROM_TB_EDGE_TAG}", getTagVersion(currentEdgeVersion)); |
|||
linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${TB_EDGE_VERSION}", edgeVersion); |
|||
linuxUpgradeInstructions = linuxUpgradeInstructions.replace("${FROM_TB_EDGE_VERSION}", currentEdgeVersion); |
|||
currentEdgeVersion = edgeVersion; |
|||
edgeUpgradeInfo = upgradeVersionHashMap.get(edgeUpgradeInfo.getNextEdgeVersion()); |
|||
result.append(linuxUpgradeInstructions); |
|||
} |
|||
String startService = readFile(resolveFile("start_service.md")); |
|||
result.append(startService); |
|||
return new EdgeInstructions(result.toString()); |
|||
} |
|||
|
|||
private String getTagVersion(String version) { |
|||
return version.endsWith(".0") ? version.substring(0, version.length() - 2) : version; |
|||
} |
|||
|
|||
private String convertEdgeVersionToDocsFormat(String edgeVersion) { |
|||
return edgeVersion.replace("_", ".").substring(2); |
|||
} |
|||
|
|||
private String readFile(Path file) { |
|||
try { |
|||
return Files.readString(file); |
|||
} catch (IOException e) { |
|||
log.warn("Failed to read file: {}", file, e); |
|||
throw new RuntimeException(e); |
|||
} |
|||
} |
|||
|
|||
private Path resolveFile(String subDir, String... subDirs) { |
|||
return getEdgeInstallInstructionsDir().resolve(Paths.get(subDir, subDirs)); |
|||
} |
|||
|
|||
private Path getEdgeInstallInstructionsDir() { |
|||
return Paths.get(installScripts.getDataDir(), InstallScripts.JSON_DIR, EDGE_DIR, INSTRUCTIONS_DIR, UPGRADE_DIR); |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/** |
|||
* Copyright © 2016-2023 The Thingsboard Authors |
|||
* |
|||
* Licensed 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. |
|||
*/ |
|||
package org.thingsboard.server.service.edge.instructions; |
|||
|
|||
import org.thingsboard.server.common.data.EdgeUpgradeInfo; |
|||
import org.thingsboard.server.common.data.edge.EdgeInstructions; |
|||
|
|||
import java.util.Map; |
|||
|
|||
public interface EdgeUpgradeInstructionsService { |
|||
|
|||
EdgeInstructions getUpgradeInstructions(String edgeVersion, String upgradeMethod); |
|||
|
|||
void updateInstructionMap(Map<String, EdgeUpgradeInfo> upgradeVersions); |
|||
|
|||
void setAppVersion(String version); |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
/** |
|||
* Copyright © 2016-2023 The Thingsboard Authors |
|||
* |
|||
* Licensed 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. |
|||
*/ |
|||
package org.thingsboard.server.common.data; |
|||
|
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
|
|||
@AllArgsConstructor |
|||
@Getter |
|||
public class EdgeUpgradeInfo { |
|||
private boolean requiresUpdateDb; |
|||
private String nextEdgeVersion; |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright © 2016-2023 The Thingsboard Authors |
|||
* |
|||
* Licensed 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. |
|||
*/ |
|||
package org.thingsboard.server.common.data; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
@ApiModel |
|||
public class EdgeUpgradeMessage implements Serializable { |
|||
|
|||
private static final long serialVersionUID = 2872965507642822989L; |
|||
|
|||
@ApiModelProperty(position = 1, value = "Mapping for upgrade versions and upgrade strategy (next ver).") |
|||
private final Map<String, EdgeUpgradeInfo> edgeVersions; |
|||
} |
|||
Loading…
Reference in new issue