Commit 2eef2c0253b554d9b3c3a7f5747e411aa48609e7
Committed by
GitHub
Merge pull request #196 from thingsboard/feature/TB-65
TB-65: Unix install/upgrade scripts.
Showing
18 changed files
with
908 additions
and
26 deletions
@@ -57,6 +57,21 @@ ospackage { | @@ -57,6 +57,21 @@ ospackage { | ||
57 | into "bin" | 57 | into "bin" |
58 | } | 58 | } |
59 | 59 | ||
60 | + // Copy the install files | ||
61 | + from("target/bin/install/install.sh") { | ||
62 | + fileMode 0775 | ||
63 | + into "bin/install" | ||
64 | + } | ||
65 | + | ||
66 | + from("target/bin/install/upgrade.sh") { | ||
67 | + fileMode 0775 | ||
68 | + into "bin/install" | ||
69 | + } | ||
70 | + | ||
71 | + from("target/bin/install/logback.xml") { | ||
72 | + into "bin/install" | ||
73 | + } | ||
74 | + | ||
60 | // Copy the config files | 75 | // Copy the config files |
61 | from("target/conf") { | 76 | from("target/conf") { |
62 | exclude "${pkgName}.conf" | 77 | exclude "${pkgName}.conf" |
@@ -27,7 +27,7 @@ | @@ -27,7 +27,7 @@ | ||
27 | <artifactId>application</artifactId> | 27 | <artifactId>application</artifactId> |
28 | <packaging>jar</packaging> | 28 | <packaging>jar</packaging> |
29 | 29 | ||
30 | - <name>Thingsboard Server Application</name> | 30 | + <name>ThingsBoard Server Application</name> |
31 | <url>https://thingsboard.io</url> | 31 | <url>https://thingsboard.io</url> |
32 | <description>Open-source IoT Platform - Device management, data collection, processing and visualization | 32 | <description>Open-source IoT Platform - Device management, data collection, processing and visualization |
33 | </description> | 33 | </description> |
@@ -138,6 +138,14 @@ | @@ -138,6 +138,14 @@ | ||
138 | <artifactId>velocity-tools</artifactId> | 138 | <artifactId>velocity-tools</artifactId> |
139 | </dependency> | 139 | </dependency> |
140 | <dependency> | 140 | <dependency> |
141 | + <groupId>commons-io</groupId> | ||
142 | + <artifactId>commons-io</artifactId> | ||
143 | + </dependency> | ||
144 | + <dependency> | ||
145 | + <groupId>org.apache.commons</groupId> | ||
146 | + <artifactId>commons-csv</artifactId> | ||
147 | + </dependency> | ||
148 | + <dependency> | ||
141 | <groupId>org.springframework</groupId> | 149 | <groupId>org.springframework</groupId> |
142 | <artifactId>spring-context-support</artifactId> | 150 | <artifactId>spring-context-support</artifactId> |
143 | </dependency> | 151 | </dependency> |
@@ -368,6 +376,29 @@ | @@ -368,6 +376,29 @@ | ||
368 | </configuration> | 376 | </configuration> |
369 | </execution> | 377 | </execution> |
370 | <execution> | 378 | <execution> |
379 | + <id>copy-install</id> | ||
380 | + <phase>process-resources</phase> | ||
381 | + <goals> | ||
382 | + <goal>copy-resources</goal> | ||
383 | + </goals> | ||
384 | + <configuration> | ||
385 | + <outputDirectory>${project.build.directory}/bin/install</outputDirectory> | ||
386 | + <resources> | ||
387 | + <resource> | ||
388 | + <directory>src/main/scripts/install</directory> | ||
389 | + <includes> | ||
390 | + <include>**/*.sh</include> | ||
391 | + <include>**/*.xml</include> | ||
392 | + </includes> | ||
393 | + <filtering>true</filtering> | ||
394 | + </resource> | ||
395 | + </resources> | ||
396 | + <filters> | ||
397 | + <filter>src/main/filters/unix.properties</filter> | ||
398 | + </filters> | ||
399 | + </configuration> | ||
400 | + </execution> | ||
401 | + <execution> | ||
371 | <id>copy-windows-control</id> | 402 | <id>copy-windows-control</id> |
372 | <phase>process-resources</phase> | 403 | <phase>process-resources</phase> |
373 | <goals> | 404 | <goals> |
@@ -387,7 +418,7 @@ | @@ -387,7 +418,7 @@ | ||
387 | </configuration> | 418 | </configuration> |
388 | </execution> | 419 | </execution> |
389 | <execution> | 420 | <execution> |
390 | - <id>copy-data-cql</id> | 421 | + <id>copy-data</id> |
391 | <phase>process-resources</phase> | 422 | <phase>process-resources</phase> |
392 | <goals> | 423 | <goals> |
393 | <goal>copy-resources</goal> | 424 | <goal>copy-resources</goal> |
@@ -396,9 +427,13 @@ | @@ -396,9 +427,13 @@ | ||
396 | <outputDirectory>${project.build.directory}/data</outputDirectory> | 427 | <outputDirectory>${project.build.directory}/data</outputDirectory> |
397 | <resources> | 428 | <resources> |
398 | <resource> | 429 | <resource> |
430 | + <directory>src/main/data</directory> | ||
431 | + </resource> | ||
432 | + <resource> | ||
399 | <directory>../dao/src/main/resources</directory> | 433 | <directory>../dao/src/main/resources</directory> |
400 | <includes> | 434 | <includes> |
401 | <include>**/*.cql</include> | 435 | <include>**/*.cql</include> |
436 | + <include>**/*.sql</include> | ||
402 | </includes> | 437 | </includes> |
403 | <filtering>false</filtering> | 438 | <filtering>false</filtering> |
404 | </resource> | 439 | </resource> |
1 | +-- | ||
2 | +-- Copyright © 2016-2017 The Thingsboard Authors | ||
3 | +-- | ||
4 | +-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +-- you may not use this file except in compliance with the License. | ||
6 | +-- You may obtain a copy of the License at | ||
7 | +-- | ||
8 | +-- http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +-- | ||
10 | +-- Unless required by applicable law or agreed to in writing, software | ||
11 | +-- distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +-- See the License for the specific language governing permissions and | ||
14 | +-- limitations under the License. | ||
15 | +-- | ||
16 | + | ||
17 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.device_by_tenant_and_name; | ||
18 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.device_by_tenant_and_search_text; | ||
19 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.device_by_tenant_by_type_and_search_text; | ||
20 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.device_by_customer_and_search_text; | ||
21 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.device_by_customer_by_type_and_search_text; | ||
22 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.device_types_by_tenant; | ||
23 | + | ||
24 | +DROP TABLE IF EXISTS thingsboard.device; | ||
25 | + | ||
26 | +CREATE TABLE IF NOT EXISTS thingsboard.device ( | ||
27 | + id timeuuid, | ||
28 | + tenant_id timeuuid, | ||
29 | + customer_id timeuuid, | ||
30 | + name text, | ||
31 | + type text, | ||
32 | + search_text text, | ||
33 | + additional_info text, | ||
34 | + PRIMARY KEY (id, tenant_id, customer_id, type) | ||
35 | +); | ||
36 | + | ||
37 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_and_name AS | ||
38 | + SELECT * | ||
39 | + from thingsboard.device | ||
40 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL | ||
41 | + PRIMARY KEY ( tenant_id, name, id, customer_id, type) | ||
42 | + WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); | ||
43 | + | ||
44 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_and_search_text AS | ||
45 | + SELECT * | ||
46 | + from thingsboard.device | ||
47 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
48 | + PRIMARY KEY ( tenant_id, search_text, id, customer_id, type) | ||
49 | + WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC); | ||
50 | + | ||
51 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_tenant_by_type_and_search_text AS | ||
52 | + SELECT * | ||
53 | + from thingsboard.device | ||
54 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
55 | + PRIMARY KEY ( tenant_id, type, search_text, id, customer_id) | ||
56 | + WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC, customer_id DESC); | ||
57 | + | ||
58 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_and_search_text AS | ||
59 | + SELECT * | ||
60 | + from thingsboard.device | ||
61 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
62 | + PRIMARY KEY ( customer_id, tenant_id, search_text, id, type ) | ||
63 | + WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC ); | ||
64 | + | ||
65 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_and_search_text AS | ||
66 | + SELECT * | ||
67 | + from thingsboard.device | ||
68 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
69 | + PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) | ||
70 | + WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); | ||
71 | + | ||
72 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS | ||
73 | + SELECT * | ||
74 | + from thingsboard.device | ||
75 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL | ||
76 | + PRIMARY KEY ( (type, tenant_id), id, customer_id) | ||
77 | + WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); | ||
78 | + | ||
79 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_name; | ||
80 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_search_text; | ||
81 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_by_type_and_search_text; | ||
82 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_customer_and_search_text; | ||
83 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_customer_by_type_and_search_text; | ||
84 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_types_by_tenant; | ||
85 | + | ||
86 | +DROP TABLE IF EXISTS thingsboard.asset; | ||
87 | + | ||
88 | +CREATE TABLE IF NOT EXISTS thingsboard.asset ( | ||
89 | + id timeuuid, | ||
90 | + tenant_id timeuuid, | ||
91 | + customer_id timeuuid, | ||
92 | + name text, | ||
93 | + type text, | ||
94 | + search_text text, | ||
95 | + additional_info text, | ||
96 | + PRIMARY KEY (id, tenant_id, customer_id, type) | ||
97 | +); | ||
98 | + | ||
99 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_and_name AS | ||
100 | + SELECT * | ||
101 | + from thingsboard.asset | ||
102 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND name IS NOT NULL AND id IS NOT NULL | ||
103 | + PRIMARY KEY ( tenant_id, name, id, customer_id, type) | ||
104 | + WITH CLUSTERING ORDER BY ( name ASC, id DESC, customer_id DESC); | ||
105 | + | ||
106 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_and_search_text AS | ||
107 | + SELECT * | ||
108 | + from thingsboard.asset | ||
109 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
110 | + PRIMARY KEY ( tenant_id, search_text, id, customer_id, type) | ||
111 | + WITH CLUSTERING ORDER BY ( search_text ASC, id DESC, customer_id DESC); | ||
112 | + | ||
113 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_tenant_by_type_and_search_text AS | ||
114 | + SELECT * | ||
115 | + from thingsboard.asset | ||
116 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
117 | + PRIMARY KEY ( tenant_id, type, search_text, id, customer_id) | ||
118 | + WITH CLUSTERING ORDER BY ( type ASC, search_text ASC, id DESC, customer_id DESC); | ||
119 | + | ||
120 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_and_search_text AS | ||
121 | + SELECT * | ||
122 | + from thingsboard.asset | ||
123 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
124 | + PRIMARY KEY ( customer_id, tenant_id, search_text, id, type ) | ||
125 | + WITH CLUSTERING ORDER BY ( tenant_id DESC, search_text ASC, id DESC ); | ||
126 | + | ||
127 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and_search_text AS | ||
128 | + SELECT * | ||
129 | + from thingsboard.asset | ||
130 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND search_text IS NOT NULL AND id IS NOT NULL | ||
131 | + PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) | ||
132 | + WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); | ||
133 | + | ||
134 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS | ||
135 | + SELECT * | ||
136 | + from thingsboard.asset | ||
137 | + WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL | ||
138 | + PRIMARY KEY ( (type, tenant_id), id, customer_id) | ||
139 | + WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); | ||
140 | + | ||
141 | +CREATE TABLE IF NOT EXISTS thingsboard.alarm ( | ||
142 | + id timeuuid, | ||
143 | + tenant_id timeuuid, | ||
144 | + type text, | ||
145 | + originator_id timeuuid, | ||
146 | + originator_type text, | ||
147 | + severity text, | ||
148 | + status text, | ||
149 | + start_ts bigint, | ||
150 | + end_ts bigint, | ||
151 | + ack_ts bigint, | ||
152 | + clear_ts bigint, | ||
153 | + details text, | ||
154 | + propagate boolean, | ||
155 | + PRIMARY KEY ((tenant_id, originator_id, originator_type), type, id) | ||
156 | +) WITH CLUSTERING ORDER BY ( type ASC, id DESC); | ||
157 | + | ||
158 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.alarm_by_id AS | ||
159 | + SELECT * | ||
160 | + from thingsboard.alarm | ||
161 | + WHERE tenant_id IS NOT NULL AND originator_id IS NOT NULL AND originator_type IS NOT NULL AND type IS NOT NULL | ||
162 | + AND type IS NOT NULL AND id IS NOT NULL | ||
163 | + PRIMARY KEY (id, tenant_id, originator_id, originator_type, type) | ||
164 | + WITH CLUSTERING ORDER BY ( tenant_id ASC, originator_id ASC, originator_type ASC, type ASC); | ||
165 | + | ||
166 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.relation_by_type_and_child_type; | ||
167 | +DROP MATERIALIZED VIEW IF EXISTS thingsboard.reverse_relation; | ||
168 | + | ||
169 | +DROP TABLE IF EXISTS thingsboard.relation; | ||
170 | + | ||
171 | +CREATE TABLE IF NOT EXISTS thingsboard.relation ( | ||
172 | + from_id timeuuid, | ||
173 | + from_type text, | ||
174 | + to_id timeuuid, | ||
175 | + to_type text, | ||
176 | + relation_type_group text, | ||
177 | + relation_type text, | ||
178 | + additional_info text, | ||
179 | + PRIMARY KEY ((from_id, from_type), relation_type_group, relation_type, to_id, to_type) | ||
180 | +) WITH CLUSTERING ORDER BY ( relation_type_group ASC, relation_type ASC, to_id ASC, to_type ASC); | ||
181 | + | ||
182 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.relation_by_type_and_child_type AS | ||
183 | + SELECT * | ||
184 | + from thingsboard.relation | ||
185 | + WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type_group IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL | ||
186 | + PRIMARY KEY ((from_id, from_type), relation_type_group, relation_type, to_type, to_id) | ||
187 | + WITH CLUSTERING ORDER BY ( relation_type_group ASC, relation_type ASC, to_type ASC, to_id DESC); | ||
188 | + | ||
189 | +CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.reverse_relation AS | ||
190 | + SELECT * | ||
191 | + from thingsboard.relation | ||
192 | + WHERE from_id IS NOT NULL AND from_type IS NOT NULL AND relation_type_group IS NOT NULL AND relation_type IS NOT NULL AND to_id IS NOT NULL AND to_type IS NOT NULL | ||
193 | + PRIMARY KEY ((to_id, to_type), relation_type_group, relation_type, from_id, from_type) | ||
194 | + WITH CLUSTERING ORDER BY ( relation_type_group ASC, relation_type ASC, from_id ASC, from_type ASC); |
@@ -25,6 +25,7 @@ import org.springframework.context.annotation.Profile; | @@ -25,6 +25,7 @@ import org.springframework.context.annotation.Profile; | ||
25 | import org.springframework.stereotype.Service; | 25 | import org.springframework.stereotype.Service; |
26 | import org.thingsboard.server.service.component.ComponentDiscoveryService; | 26 | import org.thingsboard.server.service.component.ComponentDiscoveryService; |
27 | import org.thingsboard.server.service.install.DatabaseSchemaService; | 27 | import org.thingsboard.server.service.install.DatabaseSchemaService; |
28 | +import org.thingsboard.server.service.install.DatabaseUpgradeService; | ||
28 | import org.thingsboard.server.service.install.SystemDataLoaderService; | 29 | import org.thingsboard.server.service.install.SystemDataLoaderService; |
29 | 30 | ||
30 | import java.nio.file.Files; | 31 | import java.nio.file.Files; |
@@ -35,6 +36,12 @@ import java.nio.file.Paths; | @@ -35,6 +36,12 @@ import java.nio.file.Paths; | ||
35 | @Slf4j | 36 | @Slf4j |
36 | public class ThingsboardInstallService { | 37 | public class ThingsboardInstallService { |
37 | 38 | ||
39 | + @Value("${install.upgrade:false}") | ||
40 | + private Boolean isUpgrade; | ||
41 | + | ||
42 | + @Value("${install.upgrade.from_version:1.2.3}") | ||
43 | + private String upgradeFromVersion; | ||
44 | + | ||
38 | @Value("${install.data_dir}") | 45 | @Value("${install.data_dir}") |
39 | private String dataDir; | 46 | private String dataDir; |
40 | 47 | ||
@@ -45,6 +52,9 @@ public class ThingsboardInstallService { | @@ -45,6 +52,9 @@ public class ThingsboardInstallService { | ||
45 | private DatabaseSchemaService databaseSchemaService; | 52 | private DatabaseSchemaService databaseSchemaService; |
46 | 53 | ||
47 | @Autowired | 54 | @Autowired |
55 | + private DatabaseUpgradeService databaseUpgradeService; | ||
56 | + | ||
57 | + @Autowired | ||
48 | private ComponentDiscoveryService componentDiscoveryService; | 58 | private ComponentDiscoveryService componentDiscoveryService; |
49 | 59 | ||
50 | @Autowired | 60 | @Autowired |
@@ -55,35 +65,67 @@ public class ThingsboardInstallService { | @@ -55,35 +65,67 @@ public class ThingsboardInstallService { | ||
55 | 65 | ||
56 | public void performInstall() { | 66 | public void performInstall() { |
57 | try { | 67 | try { |
58 | - log.info("Starting ThingsBoard Installation..."); | 68 | + if (isUpgrade) { |
69 | + log.info("Starting ThingsBoard Upgrade from version {} ...", upgradeFromVersion); | ||
59 | 70 | ||
60 | - if (this.dataDir == null) { | ||
61 | - throw new RuntimeException("'install.data_dir' property should specified!"); | ||
62 | - } | ||
63 | - if (!Files.isDirectory(Paths.get(this.dataDir))) { | ||
64 | - throw new RuntimeException("'install.data_dir' property value is not a valid directory!"); | ||
65 | - } | 71 | + switch (upgradeFromVersion) { |
72 | + case "1.2.3": | ||
73 | + log.info("Upgrading ThingsBoard from version {} to 1.3.0 ...", upgradeFromVersion); | ||
74 | + | ||
75 | + databaseUpgradeService.upgradeDatabase(upgradeFromVersion); | ||
76 | + | ||
77 | + log.info("Updating system data..."); | ||
66 | 78 | ||
67 | - log.info("Installing DataBase schema..."); | 79 | + systemDataLoaderService.deleteSystemWidgetBundle("charts"); |
80 | + systemDataLoaderService.deleteSystemWidgetBundle("cards"); | ||
81 | + systemDataLoaderService.deleteSystemWidgetBundle("maps"); | ||
82 | + systemDataLoaderService.deleteSystemWidgetBundle("analogue_gauges"); | ||
83 | + systemDataLoaderService.deleteSystemWidgetBundle("digital_gauges"); | ||
84 | + systemDataLoaderService.deleteSystemWidgetBundle("gpio_widgets"); | ||
85 | + systemDataLoaderService.deleteSystemWidgetBundle("alarm_widgets"); | ||
68 | 86 | ||
69 | - databaseSchemaService.createDatabaseSchema(); | 87 | + systemDataLoaderService.loadSystemWidgets(); |
70 | 88 | ||
71 | - log.info("Loading system data..."); | 89 | + break; |
90 | + default: | ||
91 | + throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion); | ||
72 | 92 | ||
73 | - componentDiscoveryService.discoverComponents(); | 93 | + } |
94 | + log.info("Upgrade finished successfully!"); | ||
74 | 95 | ||
75 | - systemDataLoaderService.createSysAdmin(); | ||
76 | - systemDataLoaderService.createAdminSettings(); | ||
77 | - systemDataLoaderService.loadSystemWidgets(); | ||
78 | - systemDataLoaderService.loadSystemPlugins(); | ||
79 | - systemDataLoaderService.loadSystemRules(); | 96 | + } else { |
80 | 97 | ||
81 | - if (loadDemo) { | ||
82 | - log.info("Loading demo data..."); | ||
83 | - systemDataLoaderService.loadDemoData(); | 98 | + log.info("Starting ThingsBoard Installation..."); |
99 | + | ||
100 | + if (this.dataDir == null) { | ||
101 | + throw new RuntimeException("'install.data_dir' property should specified!"); | ||
102 | + } | ||
103 | + if (!Files.isDirectory(Paths.get(this.dataDir))) { | ||
104 | + throw new RuntimeException("'install.data_dir' property value is not a valid directory!"); | ||
105 | + } | ||
106 | + | ||
107 | + log.info("Installing DataBase schema..."); | ||
108 | + | ||
109 | + databaseSchemaService.createDatabaseSchema(); | ||
110 | + | ||
111 | + log.info("Loading system data..."); | ||
112 | + | ||
113 | + componentDiscoveryService.discoverComponents(); | ||
114 | + | ||
115 | + systemDataLoaderService.createSysAdmin(); | ||
116 | + systemDataLoaderService.createAdminSettings(); | ||
117 | + systemDataLoaderService.loadSystemWidgets(); | ||
118 | + systemDataLoaderService.loadSystemPlugins(); | ||
119 | + systemDataLoaderService.loadSystemRules(); | ||
120 | + | ||
121 | + if (loadDemo) { | ||
122 | + log.info("Loading demo data..."); | ||
123 | + systemDataLoaderService.loadDemoData(); | ||
124 | + } | ||
125 | + log.info("Installation finished successfully!"); | ||
84 | } | 126 | } |
85 | 127 | ||
86 | - log.info("Finished!"); | 128 | + |
87 | } catch (Exception e) { | 129 | } catch (Exception e) { |
88 | log.error("Unexpected error during ThingsBoard installation!", e); | 130 | log.error("Unexpected error during ThingsBoard installation!", e); |
89 | throw new ThingsboardInstallException("Unexpected error during ThingsBoard installation!", e); | 131 | throw new ThingsboardInstallException("Unexpected error during ThingsBoard installation!", e); |
application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseSchemaService.java
@@ -23,7 +23,7 @@ import org.springframework.context.annotation.Profile; | @@ -23,7 +23,7 @@ import org.springframework.context.annotation.Profile; | ||
23 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
24 | import org.thingsboard.server.dao.cassandra.CassandraInstallCluster; | 24 | import org.thingsboard.server.dao.cassandra.CassandraInstallCluster; |
25 | import org.thingsboard.server.dao.util.NoSqlDao; | 25 | import org.thingsboard.server.dao.util.NoSqlDao; |
26 | -import org.thingsboard.server.install.cql.CQLStatementsParser; | 26 | +import org.thingsboard.server.service.install.cql.CQLStatementsParser; |
27 | 27 | ||
28 | import java.nio.file.Path; | 28 | import java.nio.file.Path; |
29 | import java.nio.file.Paths; | 29 | import java.nio.file.Paths; |
@@ -35,6 +35,7 @@ import java.util.List; | @@ -35,6 +35,7 @@ import java.util.List; | ||
35 | @Slf4j | 35 | @Slf4j |
36 | public class CassandraDatabaseSchemaService implements DatabaseSchemaService { | 36 | public class CassandraDatabaseSchemaService implements DatabaseSchemaService { |
37 | 37 | ||
38 | + private static final String CASSANDRA_DIR = "cassandra"; | ||
38 | private static final String SCHEMA_CQL = "schema.cql"; | 39 | private static final String SCHEMA_CQL = "schema.cql"; |
39 | 40 | ||
40 | @Value("${install.data_dir}") | 41 | @Value("${install.data_dir}") |
@@ -47,7 +48,7 @@ public class CassandraDatabaseSchemaService implements DatabaseSchemaService { | @@ -47,7 +48,7 @@ public class CassandraDatabaseSchemaService implements DatabaseSchemaService { | ||
47 | public void createDatabaseSchema() throws Exception { | 48 | public void createDatabaseSchema() throws Exception { |
48 | log.info("Installing Cassandra DataBase schema..."); | 49 | log.info("Installing Cassandra DataBase schema..."); |
49 | 50 | ||
50 | - Path schemaFile = Paths.get(this.dataDir, SCHEMA_CQL); | 51 | + Path schemaFile = Paths.get(this.dataDir, CASSANDRA_DIR, SCHEMA_CQL); |
51 | loadCql(schemaFile); | 52 | loadCql(schemaFile); |
52 | 53 | ||
53 | } | 54 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.service.install; | ||
18 | + | ||
19 | +import com.datastax.driver.core.KeyspaceMetadata; | ||
20 | +import lombok.extern.slf4j.Slf4j; | ||
21 | +import org.springframework.beans.factory.annotation.Autowired; | ||
22 | +import org.springframework.beans.factory.annotation.Value; | ||
23 | +import org.springframework.context.annotation.Profile; | ||
24 | +import org.springframework.stereotype.Service; | ||
25 | +import org.thingsboard.server.dao.cassandra.CassandraCluster; | ||
26 | +import org.thingsboard.server.dao.cassandra.CassandraInstallCluster; | ||
27 | +import org.thingsboard.server.dao.util.NoSqlDao; | ||
28 | +import org.thingsboard.server.service.install.cql.CQLStatementsParser; | ||
29 | +import org.thingsboard.server.service.install.cql.CassandraDbHelper; | ||
30 | + | ||
31 | +import java.nio.file.Files; | ||
32 | +import java.nio.file.Path; | ||
33 | +import java.nio.file.Paths; | ||
34 | +import java.util.List; | ||
35 | + | ||
36 | +@Service | ||
37 | +@NoSqlDao | ||
38 | +@Profile("install") | ||
39 | +@Slf4j | ||
40 | +public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService { | ||
41 | + | ||
42 | + private static final String SCHEMA_UPDATE_CQL = "schema_update.cql"; | ||
43 | + | ||
44 | + @Value("${install.data_dir}") | ||
45 | + private String dataDir; | ||
46 | + | ||
47 | + @Autowired | ||
48 | + private CassandraCluster cluster; | ||
49 | + | ||
50 | + @Autowired | ||
51 | + private CassandraInstallCluster installCluster; | ||
52 | + | ||
53 | + @Override | ||
54 | + public void upgradeDatabase(String fromVersion) throws Exception { | ||
55 | + | ||
56 | + switch (fromVersion) { | ||
57 | + case "1.2.3": | ||
58 | + | ||
59 | + log.info("Upgrading Cassandara DataBase from version {} to 1.3.0 ...", fromVersion); | ||
60 | + | ||
61 | + //Dump devices, assets and relations | ||
62 | + | ||
63 | + KeyspaceMetadata ks = cluster.getCluster().getMetadata().getKeyspace(cluster.getKeyspaceName()); | ||
64 | + | ||
65 | + log.info("Dumping devices ..."); | ||
66 | + Path devicesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device", | ||
67 | + new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info"}, | ||
68 | + "tb-devices"); | ||
69 | + if (devicesDump != null) { | ||
70 | + CassandraDbHelper.appendToEndOfLine(devicesDump, "default"); | ||
71 | + } | ||
72 | + log.info("Devices dumped."); | ||
73 | + | ||
74 | + log.info("Dumping assets ..."); | ||
75 | + Path assetsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset", | ||
76 | + new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"}, | ||
77 | + "tb-assets"); | ||
78 | + log.info("Assets dumped."); | ||
79 | + | ||
80 | + log.info("Dumping relations ..."); | ||
81 | + Path relationsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "relation", | ||
82 | + new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info"}, | ||
83 | + "tb-relations"); | ||
84 | + if (relationsDump != null) { | ||
85 | + CassandraDbHelper.appendToEndOfLine(relationsDump, "COMMON"); | ||
86 | + } | ||
87 | + log.info("Relations dumped."); | ||
88 | + | ||
89 | + log.info("Updating schema ..."); | ||
90 | + Path schemaUpdateFile = Paths.get(this.dataDir, "upgrade", "1.3.0", SCHEMA_UPDATE_CQL); | ||
91 | + loadCql(schemaUpdateFile); | ||
92 | + log.info("Schema updated."); | ||
93 | + | ||
94 | + //Restore devices, assets and relations | ||
95 | + | ||
96 | + log.info("Restoring devices ..."); | ||
97 | + if (devicesDump != null) { | ||
98 | + CassandraDbHelper.loadCf(ks, cluster.getSession(), "device", | ||
99 | + new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"}, devicesDump); | ||
100 | + Files.deleteIfExists(devicesDump); | ||
101 | + } | ||
102 | + log.info("Devices restored."); | ||
103 | + | ||
104 | + log.info("Restoring assets ..."); | ||
105 | + if (assetsDump != null) { | ||
106 | + CassandraDbHelper.loadCf(ks, cluster.getSession(), "asset", | ||
107 | + new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"}, assetsDump); | ||
108 | + Files.deleteIfExists(assetsDump); | ||
109 | + } | ||
110 | + log.info("Assets restored."); | ||
111 | + | ||
112 | + log.info("Restoring relations ..."); | ||
113 | + if (relationsDump != null) { | ||
114 | + CassandraDbHelper.loadCf(ks, cluster.getSession(), "relation", | ||
115 | + new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info", "relation_type_group"}, relationsDump); | ||
116 | + Files.deleteIfExists(relationsDump); | ||
117 | + } | ||
118 | + log.info("Relations restored."); | ||
119 | + | ||
120 | + break; | ||
121 | + default: | ||
122 | + throw new RuntimeException("Unable to upgrade Cassandra database, unsupported fromVersion: " + fromVersion); | ||
123 | + } | ||
124 | + | ||
125 | + } | ||
126 | + | ||
127 | + private void loadCql(Path cql) throws Exception { | ||
128 | + List<String> statements = new CQLStatementsParser(cql).getStatements(); | ||
129 | + statements.forEach(statement -> installCluster.getSession().execute(statement)); | ||
130 | + } | ||
131 | + | ||
132 | +} |
application/src/main/java/org/thingsboard/server/service/install/DatabaseUpgradeService.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.service.install; | ||
18 | + | ||
19 | +public interface DatabaseUpgradeService { | ||
20 | + | ||
21 | + void upgradeDatabase(String fromVersion) throws Exception; | ||
22 | + | ||
23 | +} |
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
@@ -41,6 +41,7 @@ import org.thingsboard.server.dao.customer.CustomerService; | @@ -41,6 +41,7 @@ import org.thingsboard.server.dao.customer.CustomerService; | ||
41 | import org.thingsboard.server.dao.dashboard.DashboardService; | 41 | import org.thingsboard.server.dao.dashboard.DashboardService; |
42 | import org.thingsboard.server.dao.device.DeviceCredentialsService; | 42 | import org.thingsboard.server.dao.device.DeviceCredentialsService; |
43 | import org.thingsboard.server.dao.device.DeviceService; | 43 | import org.thingsboard.server.dao.device.DeviceService; |
44 | +import org.thingsboard.server.dao.model.ModelConstants; | ||
44 | import org.thingsboard.server.dao.plugin.PluginService; | 45 | import org.thingsboard.server.dao.plugin.PluginService; |
45 | import org.thingsboard.server.dao.rule.RuleService; | 46 | import org.thingsboard.server.dao.rule.RuleService; |
46 | import org.thingsboard.server.dao.settings.AdminSettingsService; | 47 | import org.thingsboard.server.dao.settings.AdminSettingsService; |
@@ -227,6 +228,14 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | @@ -227,6 +228,14 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { | ||
227 | loadDashboards(Paths.get(dataDir, JSON_DIR, DEMO_DIR, DASHBOARDS_DIR), demoTenant.getId(), null); | 228 | loadDashboards(Paths.get(dataDir, JSON_DIR, DEMO_DIR, DASHBOARDS_DIR), demoTenant.getId(), null); |
228 | } | 229 | } |
229 | 230 | ||
231 | + @Override | ||
232 | + public void deleteSystemWidgetBundle(String bundleAlias) throws Exception { | ||
233 | + WidgetsBundle widgetsBundle = widgetsBundleService.findWidgetsBundleByTenantIdAndAlias(new TenantId(ModelConstants.NULL_UUID), bundleAlias); | ||
234 | + if (widgetsBundle != null) { | ||
235 | + widgetsBundleService.deleteWidgetsBundle(widgetsBundle.getId()); | ||
236 | + } | ||
237 | + } | ||
238 | + | ||
230 | private User createUser(Authority authority, | 239 | private User createUser(Authority authority, |
231 | TenantId tenantId, | 240 | TenantId tenantId, |
232 | CustomerId customerId, | 241 | CustomerId customerId, |
@@ -22,20 +22,44 @@ import org.springframework.context.annotation.Profile; | @@ -22,20 +22,44 @@ import org.springframework.context.annotation.Profile; | ||
22 | import org.springframework.stereotype.Service; | 22 | import org.springframework.stereotype.Service; |
23 | import org.thingsboard.server.dao.util.SqlDao; | 23 | import org.thingsboard.server.dao.util.SqlDao; |
24 | 24 | ||
25 | +import java.nio.charset.Charset; | ||
26 | +import java.nio.file.Files; | ||
27 | +import java.nio.file.Path; | ||
28 | +import java.nio.file.Paths; | ||
29 | +import java.sql.Connection; | ||
30 | +import java.sql.DriverManager; | ||
31 | + | ||
25 | @Service | 32 | @Service |
26 | @Profile("install") | 33 | @Profile("install") |
27 | @Slf4j | 34 | @Slf4j |
28 | @SqlDao | 35 | @SqlDao |
29 | public class SqlDatabaseSchemaService implements DatabaseSchemaService { | 36 | public class SqlDatabaseSchemaService implements DatabaseSchemaService { |
30 | 37 | ||
38 | + private static final String SQL_DIR = "sql"; | ||
39 | + private static final String SCHEMA_SQL = "schema.sql"; | ||
40 | + | ||
31 | @Value("${install.data_dir}") | 41 | @Value("${install.data_dir}") |
32 | private String dataDir; | 42 | private String dataDir; |
33 | 43 | ||
44 | + @Value("${spring.datasource.url}") | ||
45 | + private String dbUrl; | ||
46 | + | ||
47 | + @Value("${spring.datasource.username}") | ||
48 | + private String dbUserName; | ||
49 | + | ||
50 | + @Value("${spring.datasource.password}") | ||
51 | + private String dbPassword; | ||
52 | + | ||
34 | @Override | 53 | @Override |
35 | public void createDatabaseSchema() throws Exception { | 54 | public void createDatabaseSchema() throws Exception { |
36 | 55 | ||
37 | log.info("Installing SQL DataBase schema..."); | 56 | log.info("Installing SQL DataBase schema..."); |
38 | - //TODO: | 57 | + |
58 | + Path schemaFile = Paths.get(this.dataDir, SQL_DIR, SCHEMA_SQL); | ||
59 | + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | ||
60 | + String sql = new String(Files.readAllBytes(schemaFile), Charset.forName("UTF-8")); | ||
61 | + conn.createStatement().execute(sql); | ||
62 | + } | ||
39 | 63 | ||
40 | } | 64 | } |
41 | 65 |
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.service.install; | ||
18 | + | ||
19 | +import lombok.extern.slf4j.Slf4j; | ||
20 | +import org.springframework.context.annotation.Profile; | ||
21 | +import org.springframework.stereotype.Service; | ||
22 | +import org.thingsboard.server.dao.util.SqlDao; | ||
23 | + | ||
24 | +@Service | ||
25 | +@Profile("install") | ||
26 | +@Slf4j | ||
27 | +@SqlDao | ||
28 | +public class SqlDatabaseUpgradeService implements DatabaseUpgradeService { | ||
29 | + | ||
30 | + @Override | ||
31 | + public void upgradeDatabase(String fromVersion) throws Exception { | ||
32 | + switch (fromVersion) { | ||
33 | + default: | ||
34 | + throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); | ||
35 | + } | ||
36 | + } | ||
37 | +} |
@@ -29,4 +29,6 @@ public interface SystemDataLoaderService { | @@ -29,4 +29,6 @@ public interface SystemDataLoaderService { | ||
29 | 29 | ||
30 | void loadDemoData() throws Exception; | 30 | void loadDemoData() throws Exception; |
31 | 31 | ||
32 | + void deleteSystemWidgetBundle(String bundleAlias) throws Exception; | ||
33 | + | ||
32 | } | 34 | } |
application/src/main/java/org/thingsboard/server/service/install/cql/CQLStatementsParser.java
renamed from
application/src/main/java/org/thingsboard/server/install/cql/CQLStatementsParser.java
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -package org.thingsboard.server.install.cql; | 17 | +package org.thingsboard.server.service.install.cql; |
18 | 18 | ||
19 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
20 | 20 |
application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java
0 → 100644
1 | +/** | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.thingsboard.server.service.install.cql; | ||
18 | + | ||
19 | +import com.datastax.driver.core.*; | ||
20 | +import org.apache.commons.csv.CSVFormat; | ||
21 | +import org.apache.commons.csv.CSVParser; | ||
22 | +import org.apache.commons.csv.CSVPrinter; | ||
23 | +import org.apache.commons.csv.CSVRecord; | ||
24 | + | ||
25 | +import java.io.IOException; | ||
26 | +import java.nio.file.Files; | ||
27 | +import java.nio.file.Path; | ||
28 | +import java.nio.file.StandardCopyOption; | ||
29 | +import java.util.*; | ||
30 | + | ||
31 | +public class CassandraDbHelper { | ||
32 | + | ||
33 | + private static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N"); | ||
34 | + | ||
35 | + public static Path dumpCfIfExists(KeyspaceMetadata ks, Session session, String cfName, | ||
36 | + String[] columns, String dumpPrefix) throws Exception { | ||
37 | + if (ks.getTable(cfName) != null) { | ||
38 | + Path dumpFile = Files.createTempFile(dumpPrefix, null); | ||
39 | + Files.deleteIfExists(dumpFile); | ||
40 | + try (CSVPrinter csvPrinter = new CSVPrinter(Files.newBufferedWriter(dumpFile), CSV_DUMP_FORMAT)) { | ||
41 | + Statement stmt = new SimpleStatement("SELECT * FROM " + cfName); | ||
42 | + stmt.setFetchSize(1000); | ||
43 | + ResultSet rs = session.execute(stmt); | ||
44 | + Iterator<Row> iter = rs.iterator(); | ||
45 | + while (iter.hasNext()) { | ||
46 | + Row row = iter.next(); | ||
47 | + if (row != null) { | ||
48 | + dumpRow(row, columns, csvPrinter); | ||
49 | + } | ||
50 | + } | ||
51 | + } | ||
52 | + return dumpFile; | ||
53 | + } else { | ||
54 | + return null; | ||
55 | + } | ||
56 | + } | ||
57 | + | ||
58 | + public static void appendToEndOfLine(Path targetDumpFile, String toAppend) throws Exception { | ||
59 | + Path tmp = Files.createTempFile(null, null); | ||
60 | + try (CSVParser csvParser = new CSVParser(Files.newBufferedReader(targetDumpFile), CSV_DUMP_FORMAT)) { | ||
61 | + try (CSVPrinter csvPrinter = new CSVPrinter(Files.newBufferedWriter(tmp), CSV_DUMP_FORMAT)) { | ||
62 | + csvParser.forEach(record -> { | ||
63 | + List<String> newRecord = new ArrayList<>(); | ||
64 | + record.forEach(val -> newRecord.add(val)); | ||
65 | + newRecord.add(toAppend); | ||
66 | + try { | ||
67 | + csvPrinter.printRecord(newRecord); | ||
68 | + } catch (IOException e) { | ||
69 | + throw new RuntimeException("Error appending to EOL", e); | ||
70 | + } | ||
71 | + }); | ||
72 | + } | ||
73 | + } | ||
74 | + Files.move(tmp, targetDumpFile, StandardCopyOption.REPLACE_EXISTING); | ||
75 | + } | ||
76 | + | ||
77 | + public static void loadCf(KeyspaceMetadata ks, Session session, String cfName, String[] columns, Path sourceFile) throws Exception { | ||
78 | + TableMetadata tableMetadata = ks.getTable(cfName); | ||
79 | + PreparedStatement prepared = session.prepare(createInsertStatement(cfName, columns)); | ||
80 | + try (CSVParser csvParser = new CSVParser(Files.newBufferedReader(sourceFile), CSV_DUMP_FORMAT.withHeader(columns))) { | ||
81 | + csvParser.forEach(record -> { | ||
82 | + BoundStatement boundStatement = prepared.bind(); | ||
83 | + for (String column : columns) { | ||
84 | + setColumnValue(tableMetadata, column, record, boundStatement); | ||
85 | + } | ||
86 | + session.execute(boundStatement); | ||
87 | + }); | ||
88 | + } | ||
89 | + } | ||
90 | + | ||
91 | + | ||
92 | + private static void dumpRow(Row row, String[] columns, CSVPrinter csvPrinter) throws Exception { | ||
93 | + List<String> record = new ArrayList<>(); | ||
94 | + for (String column : columns) { | ||
95 | + record.add(getColumnValue(column, row)); | ||
96 | + } | ||
97 | + csvPrinter.printRecord(record); | ||
98 | + } | ||
99 | + | ||
100 | + private static String getColumnValue(String column, Row row) { | ||
101 | + String str = ""; | ||
102 | + int index = row.getColumnDefinitions().getIndexOf(column); | ||
103 | + if (index > -1) { | ||
104 | + DataType type = row.getColumnDefinitions().getType(index); | ||
105 | + try { | ||
106 | + if (row.isNull(index)) { | ||
107 | + return null; | ||
108 | + } else if (type == DataType.cdouble()) { | ||
109 | + str = new Double(row.getDouble(index)).toString(); | ||
110 | + } else if (type == DataType.cint()) { | ||
111 | + str = new Integer(row.getInt(index)).toString(); | ||
112 | + } else if (type == DataType.uuid()) { | ||
113 | + str = row.getUUID(index).toString(); | ||
114 | + } else if (type == DataType.timeuuid()) { | ||
115 | + str = row.getUUID(index).toString(); | ||
116 | + } else if (type == DataType.cfloat()) { | ||
117 | + str = new Float(row.getFloat(index)).toString(); | ||
118 | + } else if (type == DataType.timestamp()) { | ||
119 | + str = ""+row.getTimestamp(index).getTime(); | ||
120 | + } else { | ||
121 | + str = row.getString(index); | ||
122 | + } | ||
123 | + } catch (Exception e) { | ||
124 | + str = ""; | ||
125 | + } | ||
126 | + } | ||
127 | + return str; | ||
128 | + } | ||
129 | + | ||
130 | + private static String createInsertStatement(String cfName, String[] columns) { | ||
131 | + StringBuilder insertStatementBuilder = new StringBuilder(); | ||
132 | + insertStatementBuilder.append("INSERT INTO ").append(cfName).append(" ("); | ||
133 | + for (String column : columns) { | ||
134 | + insertStatementBuilder.append(column).append(","); | ||
135 | + } | ||
136 | + insertStatementBuilder.deleteCharAt(insertStatementBuilder.length() - 1); | ||
137 | + insertStatementBuilder.append(") VALUES ("); | ||
138 | + for (String column : columns) { | ||
139 | + insertStatementBuilder.append("?").append(","); | ||
140 | + } | ||
141 | + insertStatementBuilder.deleteCharAt(insertStatementBuilder.length() - 1); | ||
142 | + insertStatementBuilder.append(")"); | ||
143 | + return insertStatementBuilder.toString(); | ||
144 | + } | ||
145 | + | ||
146 | + private static void setColumnValue(TableMetadata tableMetadata, String column, | ||
147 | + CSVRecord record, BoundStatement boundStatement) { | ||
148 | + String value = record.get(column); | ||
149 | + DataType type = tableMetadata.getColumn(column).getType(); | ||
150 | + if (value == null) { | ||
151 | + boundStatement.setToNull(column); | ||
152 | + } else if (type == DataType.cdouble()) { | ||
153 | + boundStatement.setDouble(column, Double.valueOf(value)); | ||
154 | + } else if (type == DataType.cint()) { | ||
155 | + boundStatement.setInt(column, Integer.valueOf(value)); | ||
156 | + } else if (type == DataType.uuid()) { | ||
157 | + boundStatement.setUUID(column, UUID.fromString(value)); | ||
158 | + } else if (type == DataType.timeuuid()) { | ||
159 | + boundStatement.setUUID(column, UUID.fromString(value)); | ||
160 | + } else if (type == DataType.cfloat()) { | ||
161 | + boundStatement.setFloat(column, Float.valueOf(value)); | ||
162 | + } else if (type == DataType.timestamp()) { | ||
163 | + boundStatement.setTimestamp(column, new Date(Long.valueOf(value))); | ||
164 | + } else { | ||
165 | + boundStatement.setString(column, value); | ||
166 | + } | ||
167 | + } | ||
168 | + | ||
169 | +} |
1 | +#!/bin/bash | ||
2 | +# | ||
3 | +# Copyright © 2016-2017 The Thingsboard Authors | ||
4 | +# | ||
5 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | +# you may not use this file except in compliance with the License. | ||
7 | +# You may obtain a copy of the License at | ||
8 | +# | ||
9 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +# | ||
11 | +# Unless required by applicable law or agreed to in writing, software | ||
12 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +# See the License for the specific language governing permissions and | ||
15 | +# limitations under the License. | ||
16 | +# | ||
17 | + | ||
18 | +while [[ $# -gt 0 ]] | ||
19 | +do | ||
20 | +key="$1" | ||
21 | + | ||
22 | +case $key in | ||
23 | + --loadDemo) | ||
24 | + LOAD_DEMO=true | ||
25 | + shift # past argument | ||
26 | + ;; | ||
27 | + *) | ||
28 | + # unknown option | ||
29 | + ;; | ||
30 | +esac | ||
31 | +shift # past argument or value | ||
32 | +done | ||
33 | + | ||
34 | +if [ "$LOAD_DEMO" == "true" ]; then | ||
35 | + loadDemo=true | ||
36 | +else | ||
37 | + loadDemo=false | ||
38 | +fi | ||
39 | + | ||
40 | +CONF_FOLDER=${pkg.installFolder}/conf | ||
41 | +configfile=${pkg.name}.conf | ||
42 | +jarfile=${pkg.installFolder}/bin/${pkg.name}.jar | ||
43 | +installDir=${pkg.installFolder}/data | ||
44 | + | ||
45 | +source "${CONF_FOLDER}/${configfile}" | ||
46 | + | ||
47 | +run_user=${pkg.name} | ||
48 | + | ||
49 | +su -s /bin/sh -c "java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.ThingsboardInstallApplication \ | ||
50 | + -Dinstall.data_dir=${installDir} \ | ||
51 | + -Dinstall.load_demo=${loadDemo} \ | ||
52 | + -Dspring.jpa.hibernate.ddl-auto=none \ | ||
53 | + -Dinstall.upgrade=false \ | ||
54 | + -Dlogging.config=${pkg.installFolder}/bin/install/logback.xml \ | ||
55 | + org.springframework.boot.loader.PropertiesLauncher" "$run_user" | ||
56 | + | ||
57 | +if [ $? -ne 0 ]; then | ||
58 | + echo "ThingsBoard installation failed!" | ||
59 | +else | ||
60 | + echo "ThingsBoard installed successfully!" | ||
61 | +fi | ||
62 | + | ||
63 | +exit $? |
1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
2 | +<!-- | ||
3 | + | ||
4 | + Copyright © 2016-2017 The Thingsboard Authors | ||
5 | + | ||
6 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + you may not use this file except in compliance with the License. | ||
8 | + You may obtain a copy of the License at | ||
9 | + | ||
10 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + | ||
12 | + Unless required by applicable law or agreed to in writing, software | ||
13 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + See the License for the specific language governing permissions and | ||
16 | + limitations under the License. | ||
17 | + | ||
18 | +--> | ||
19 | +<!DOCTYPE configuration> | ||
20 | +<configuration> | ||
21 | + | ||
22 | + <appender name="fileLogAppender" | ||
23 | + class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||
24 | + <file>${pkg.logFolder}/install.log</file> | ||
25 | + <rollingPolicy | ||
26 | + class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> | ||
27 | + <fileNamePattern>${pkg.logFolder}/install.%d{yyyy-MM-dd}.%i.log</fileNamePattern> | ||
28 | + <maxFileSize>100MB</maxFileSize> | ||
29 | + <maxHistory>30</maxHistory> | ||
30 | + <totalSizeCap>3GB</totalSizeCap> | ||
31 | + </rollingPolicy> | ||
32 | + <encoder> | ||
33 | + <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
34 | + </encoder> | ||
35 | + </appender> | ||
36 | + | ||
37 | + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||
38 | + <encoder> | ||
39 | + <pattern>%msg%n</pattern> | ||
40 | + </encoder> | ||
41 | + </appender> | ||
42 | + | ||
43 | + <logger name="org.thingsboard.server.install" level="INFO"> | ||
44 | + <appender-ref ref="STDOUT" /> | ||
45 | + </logger> | ||
46 | + | ||
47 | + <logger name="org.thingsboard.server.service.install" level="INFO"> | ||
48 | + <appender-ref ref="STDOUT" /> | ||
49 | + </logger> | ||
50 | + | ||
51 | + <logger name="org.thingsboard.server" level="INFO" /> | ||
52 | + <logger name="akka" level="INFO" /> | ||
53 | + | ||
54 | + <root level="INFO"> | ||
55 | + <appender-ref ref="fileLogAppender"/> | ||
56 | + </root> | ||
57 | + | ||
58 | +</configuration> |
1 | +#!/bin/bash | ||
2 | +# | ||
3 | +# Copyright © 2016-2017 The Thingsboard Authors | ||
4 | +# | ||
5 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | +# you may not use this file except in compliance with the License. | ||
7 | +# You may obtain a copy of the License at | ||
8 | +# | ||
9 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +# | ||
11 | +# Unless required by applicable law or agreed to in writing, software | ||
12 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +# See the License for the specific language governing permissions and | ||
15 | +# limitations under the License. | ||
16 | +# | ||
17 | + | ||
18 | +for i in "$@" | ||
19 | +do | ||
20 | +case $i in | ||
21 | + --fromVersion=*) | ||
22 | + FROM_VERSION="${i#*=}" | ||
23 | + shift | ||
24 | + ;; | ||
25 | + *) | ||
26 | + # unknown option | ||
27 | + ;; | ||
28 | +esac | ||
29 | +done | ||
30 | + | ||
31 | +if [[ -z "${FROM_VERSION// }" ]]; then | ||
32 | + echo "--fromVersion parameter is invalid or unspecified!" | ||
33 | + echo "Usage: upgrade.sh --fromVersion={VERSION}" | ||
34 | + exit 1 | ||
35 | +else | ||
36 | + fromVersion="${FROM_VERSION// }" | ||
37 | +fi | ||
38 | + | ||
39 | +CONF_FOLDER=${pkg.installFolder}/conf | ||
40 | +configfile=${pkg.name}.conf | ||
41 | +jarfile=${pkg.installFolder}/bin/${pkg.name}.jar | ||
42 | +installDir=${pkg.installFolder}/data | ||
43 | + | ||
44 | +source "${CONF_FOLDER}/${configfile}" | ||
45 | + | ||
46 | +run_user=${pkg.name} | ||
47 | + | ||
48 | +su -s /bin/sh -c "java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.ThingsboardInstallApplication \ | ||
49 | + -Dinstall.data_dir=${installDir} \ | ||
50 | + -Dspring.jpa.hibernate.ddl-auto=none \ | ||
51 | + -Dinstall.upgrade=true \ | ||
52 | + -Dinstall.upgrade.from_version=${fromVersion} \ | ||
53 | + -Dlogging.config=${pkg.installFolder}/bin/install/logback.xml \ | ||
54 | + org.springframework.boot.loader.PropertiesLauncher" "$run_user" | ||
55 | + | ||
56 | +if [ $? -ne 0 ]; then | ||
57 | + echo "ThingsBoard upgrade failed!" | ||
58 | +else | ||
59 | + echo "ThingsBoard upgraded successfully!" | ||
60 | +fi | ||
61 | + | ||
62 | +exit $? |
@@ -127,6 +127,10 @@ public abstract class AbstractCassandraCluster { | @@ -127,6 +127,10 @@ public abstract class AbstractCassandraCluster { | ||
127 | } | 127 | } |
128 | } | 128 | } |
129 | 129 | ||
130 | + public String getKeyspaceName() { | ||
131 | + return keyspaceName; | ||
132 | + } | ||
133 | + | ||
130 | private boolean isInstall() { | 134 | private boolean isInstall() { |
131 | return environment.acceptsProfiles("install"); | 135 | return environment.acceptsProfiles("install"); |
132 | } | 136 | } |
@@ -46,6 +46,8 @@ | @@ -46,6 +46,8 @@ | ||
46 | <guava.version>18.0</guava.version> | 46 | <guava.version>18.0</guava.version> |
47 | <commons-lang3.version>3.4</commons-lang3.version> | 47 | <commons-lang3.version>3.4</commons-lang3.version> |
48 | <commons-validator.version>1.5.0</commons-validator.version> | 48 | <commons-validator.version>1.5.0</commons-validator.version> |
49 | + <commons-io.version>2.5</commons-io.version> | ||
50 | + <commons-csv.version>1.4</commons-csv.version> | ||
49 | <jackson.version>2.8.8.1</jackson.version> | 51 | <jackson.version>2.8.8.1</jackson.version> |
50 | <json-schema-validator.version>2.2.6</json-schema-validator.version> | 52 | <json-schema-validator.version>2.2.6</json-schema-validator.version> |
51 | <scala.version>2.11</scala.version> | 53 | <scala.version>2.11</scala.version> |
@@ -566,6 +568,16 @@ | @@ -566,6 +568,16 @@ | ||
566 | <version>${commons-validator.version}</version> | 568 | <version>${commons-validator.version}</version> |
567 | </dependency> | 569 | </dependency> |
568 | <dependency> | 570 | <dependency> |
571 | + <groupId>commons-io</groupId> | ||
572 | + <artifactId>commons-io</artifactId> | ||
573 | + <version>${commons-io.version}</version> | ||
574 | + </dependency> | ||
575 | + <dependency> | ||
576 | + <groupId>org.apache.commons</groupId> | ||
577 | + <artifactId>commons-csv</artifactId> | ||
578 | + <version>${commons-csv.version}</version> | ||
579 | + </dependency> | ||
580 | + <dependency> | ||
569 | <groupId>com.fasterxml.jackson.core</groupId> | 581 | <groupId>com.fasterxml.jackson.core</groupId> |
570 | <artifactId>jackson-databind</artifactId> | 582 | <artifactId>jackson-databind</artifactId> |
571 | <version>${jackson.version}</version> | 583 | <version>${jackson.version}</version> |