Cassandra cloud connect to Datastax Astra DB using SECURE_BUNDLE, CLIENT_ID and CLIENT_SECRET
This commit is contained in:
parent
5891a1df65
commit
3c496f4749
@ -26,6 +26,7 @@ import org.thingsboard.server.service.component.ComponentDiscoveryService;
|
|||||||
import org.thingsboard.server.service.install.DatabaseEntitiesUpgradeService;
|
import org.thingsboard.server.service.install.DatabaseEntitiesUpgradeService;
|
||||||
import org.thingsboard.server.service.install.DatabaseTsUpgradeService;
|
import org.thingsboard.server.service.install.DatabaseTsUpgradeService;
|
||||||
import org.thingsboard.server.service.install.EntityDatabaseSchemaService;
|
import org.thingsboard.server.service.install.EntityDatabaseSchemaService;
|
||||||
|
import org.thingsboard.server.service.install.NoSqlKeyspaceService;
|
||||||
import org.thingsboard.server.service.install.SystemDataLoaderService;
|
import org.thingsboard.server.service.install.SystemDataLoaderService;
|
||||||
import org.thingsboard.server.service.install.TsDatabaseSchemaService;
|
import org.thingsboard.server.service.install.TsDatabaseSchemaService;
|
||||||
import org.thingsboard.server.service.install.TsLatestDatabaseSchemaService;
|
import org.thingsboard.server.service.install.TsLatestDatabaseSchemaService;
|
||||||
@ -51,6 +52,9 @@ public class ThingsboardInstallService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EntityDatabaseSchemaService entityDatabaseSchemaService;
|
private EntityDatabaseSchemaService entityDatabaseSchemaService;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private NoSqlKeyspaceService noSqlKeyspaceService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TsDatabaseSchemaService tsDatabaseSchemaService;
|
private TsDatabaseSchemaService tsDatabaseSchemaService;
|
||||||
|
|
||||||
@ -248,6 +252,10 @@ public class ThingsboardInstallService {
|
|||||||
|
|
||||||
log.info("Installing DataBase schema for timeseries...");
|
log.info("Installing DataBase schema for timeseries...");
|
||||||
|
|
||||||
|
if (noSqlKeyspaceService != null) {
|
||||||
|
noSqlKeyspaceService.createDatabaseSchema();
|
||||||
|
}
|
||||||
|
|
||||||
tsDatabaseSchemaService.createDatabaseSchema();
|
tsDatabaseSchemaService.createDatabaseSchema();
|
||||||
|
|
||||||
if (tsLatestDatabaseSchemaService != null) {
|
if (tsLatestDatabaseSchemaService != null) {
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.install;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.thingsboard.server.dao.util.NoSqlAnyDaoNonCloud;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create keyspace for Cassandra NoSQL database for non-cloud deployment.
|
||||||
|
* For cloud service like Astra DBaas admin have to create keyspace manually on cloud UI.
|
||||||
|
* Then create tokens with database admin role and put it on Thingsboard parameters.
|
||||||
|
* Without this service cloud DB will end up with exception like
|
||||||
|
* UnauthorizedException: Missing correct permission on thingsboard
|
||||||
|
* */
|
||||||
|
@Service
|
||||||
|
@NoSqlAnyDaoNonCloud
|
||||||
|
@Profile("install")
|
||||||
|
public class CassandraKeyspaceService extends CassandraAbstractDatabaseSchemaService
|
||||||
|
implements NoSqlKeyspaceService {
|
||||||
|
public CassandraKeyspaceService() {
|
||||||
|
super("schema-keyspace.cql");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.install;
|
||||||
|
|
||||||
|
public interface NoSqlKeyspaceService extends DatabaseSchemaService {
|
||||||
|
}
|
||||||
@ -200,6 +200,14 @@ cassandra:
|
|||||||
username: "${CASSANDRA_USERNAME:}"
|
username: "${CASSANDRA_USERNAME:}"
|
||||||
# Specify your password
|
# Specify your password
|
||||||
password: "${CASSANDRA_PASSWORD:}"
|
password: "${CASSANDRA_PASSWORD:}"
|
||||||
|
# Astra DB connect https://astra.datastax.com/
|
||||||
|
cloud:
|
||||||
|
# /etc/thingsboard/astra/secure-connect-thingsboard.zip
|
||||||
|
secure_connect_bundle_path: "${CASSANDRA_CLOUD_SECURE_BUNDLE_PATH:}"
|
||||||
|
# DucitQPHMzPCBOZqFYexAfKk
|
||||||
|
client_id: "${CASSANDRA_CLOUD_CLIENT_ID:}"
|
||||||
|
# ZnF7FpuHp43FP5BzM+KY8wGmSb4Ql6BhT4Z7sOU13ze+gXQ-n7OkFpNuB,oACUIQObQnK0g4bSPoZhK5ejkcF9F.j6f64j71Sr.tiRe0Fsq2hPS1ZCGSfAaIgg63IydG
|
||||||
|
client_secret: "${CASSANDRA_CLOUD_CLIENT_SECRET:}"
|
||||||
|
|
||||||
# Cassandra cluster connection socket parameters #
|
# Cassandra cluster connection socket parameters #
|
||||||
socket:
|
socket:
|
||||||
|
|||||||
@ -35,6 +35,7 @@ public class TransportNoSqlTestSuite {
|
|||||||
public static CustomCassandraCQLUnit cassandraUnit =
|
public static CustomCassandraCQLUnit cassandraUnit =
|
||||||
new CustomCassandraCQLUnit(
|
new CustomCassandraCQLUnit(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
|
new ClassPathCQLDataSet("cassandra/schema-keyspace.cql", false, false),
|
||||||
new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false),
|
new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false),
|
||||||
new ClassPathCQLDataSet("cassandra/schema-ts-latest.cql", false, false)
|
new ClassPathCQLDataSet("cassandra/schema-ts-latest.cql", false, false)
|
||||||
),
|
),
|
||||||
|
|||||||
@ -24,11 +24,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.env.Profiles;
|
import org.springframework.core.env.Profiles;
|
||||||
|
import org.thingsboard.server.common.data.StringUtils;
|
||||||
import org.thingsboard.server.dao.cassandra.guava.GuavaSession;
|
import org.thingsboard.server.dao.cassandra.guava.GuavaSession;
|
||||||
import org.thingsboard.server.dao.cassandra.guava.GuavaSessionBuilder;
|
import org.thingsboard.server.dao.cassandra.guava.GuavaSessionBuilder;
|
||||||
import org.thingsboard.server.dao.cassandra.guava.GuavaSessionUtils;
|
import org.thingsboard.server.dao.cassandra.guava.GuavaSessionUtils;
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class AbstractCassandraCluster {
|
public abstract class AbstractCassandraCluster {
|
||||||
@ -40,6 +42,13 @@ public abstract class AbstractCassandraCluster {
|
|||||||
@Value("${cassandra.local_datacenter:datacenter1}")
|
@Value("${cassandra.local_datacenter:datacenter1}")
|
||||||
private String localDatacenter;
|
private String localDatacenter;
|
||||||
|
|
||||||
|
@Value("${cassandra.cloud.secure_connect_bundle_path:}")
|
||||||
|
private String cloudSecureConnectBundlePath;
|
||||||
|
@Value("${cassandra.cloud.client_id:}")
|
||||||
|
private String cloudClientId;
|
||||||
|
@Value("${cassandra.cloud.client_secret:}")
|
||||||
|
private String cloudClientSecret;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CassandraDriverOptions driverOptions;
|
private CassandraDriverOptions driverOptions;
|
||||||
|
|
||||||
@ -86,7 +95,14 @@ public abstract class AbstractCassandraCluster {
|
|||||||
this.sessionBuilder.withKeyspace(this.keyspaceName);
|
this.sessionBuilder.withKeyspace(this.keyspaceName);
|
||||||
}
|
}
|
||||||
this.sessionBuilder.withLocalDatacenter(localDatacenter);
|
this.sessionBuilder.withLocalDatacenter(localDatacenter);
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(cloudSecureConnectBundlePath)) {
|
||||||
|
this.sessionBuilder.withCloudSecureConnectBundle(Paths.get(cloudSecureConnectBundlePath));
|
||||||
|
this.sessionBuilder.withAuthCredentials(cloudClientId, cloudClientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
session = sessionBuilder.build();
|
session = sessionBuilder.build();
|
||||||
|
|
||||||
if (this.metrics && this.jmx) {
|
if (this.metrics && this.jmx) {
|
||||||
MetricRegistry registry =
|
MetricRegistry registry =
|
||||||
session.getMetrics().orElseThrow(
|
session.getMetrics().orElseThrow(
|
||||||
|
|||||||
@ -40,26 +40,8 @@ import java.util.function.Predicate;
|
|||||||
*/
|
*/
|
||||||
public class GuavaDriverContext extends DefaultDriverContext {
|
public class GuavaDriverContext extends DefaultDriverContext {
|
||||||
|
|
||||||
public GuavaDriverContext(
|
public GuavaDriverContext(DriverConfigLoader configLoader, ProgrammaticArguments programmaticArguments) {
|
||||||
DriverConfigLoader configLoader,
|
super(configLoader, programmaticArguments);
|
||||||
List<TypeCodec<?>> typeCodecs,
|
|
||||||
NodeStateListener nodeStateListener,
|
|
||||||
SchemaChangeListener schemaChangeListener,
|
|
||||||
RequestTracker requestTracker,
|
|
||||||
Map<String, String> localDatacenters,
|
|
||||||
Map<String, Predicate<Node>> nodeFilters,
|
|
||||||
ClassLoader classLoader) {
|
|
||||||
super(
|
|
||||||
configLoader,
|
|
||||||
ProgrammaticArguments.builder()
|
|
||||||
.addTypeCodecs(typeCodecs.toArray(new TypeCodec<?>[0]))
|
|
||||||
.withNodeStateListener(nodeStateListener)
|
|
||||||
.withSchemaChangeListener(schemaChangeListener)
|
|
||||||
.withRequestTracker(requestTracker)
|
|
||||||
.withLocalDatacenters(localDatacenters)
|
|
||||||
.withNodeFilters(nodeFilters)
|
|
||||||
.withClassLoader(classLoader)
|
|
||||||
.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -25,18 +25,8 @@ import edu.umd.cs.findbugs.annotations.NonNull;
|
|||||||
public class GuavaSessionBuilder extends SessionBuilder<GuavaSessionBuilder, GuavaSession> {
|
public class GuavaSessionBuilder extends SessionBuilder<GuavaSessionBuilder, GuavaSession> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DriverContext buildContext(
|
protected DriverContext buildContext(DriverConfigLoader configLoader, ProgrammaticArguments programmaticArguments) {
|
||||||
DriverConfigLoader configLoader,
|
return new GuavaDriverContext(configLoader, programmaticArguments);
|
||||||
ProgrammaticArguments programmaticArguments) {
|
|
||||||
return new GuavaDriverContext(
|
|
||||||
configLoader,
|
|
||||||
programmaticArguments.getTypeCodecs(),
|
|
||||||
programmaticArguments.getNodeStateListener(),
|
|
||||||
programmaticArguments.getSchemaChangeListener(),
|
|
||||||
programmaticArguments.getRequestTracker(),
|
|
||||||
programmaticArguments.getLocalDatacenters(),
|
|
||||||
programmaticArguments.getNodeFilters(),
|
|
||||||
programmaticArguments.getClassLoader());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2022 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.dao.util;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@ConditionalOnExpression("('${database.ts.type}'=='cassandra' || '${database.ts_latest.type}'=='cassandra') " +
|
||||||
|
"&& ('${cassandra.cloud.secure_connect_bundle_path}' == null || '${cassandra.cloud.secure_connect_bundle_path}'.isBlank() )")
|
||||||
|
public @interface NoSqlAnyDaoNonCloud {
|
||||||
|
}
|
||||||
21
dao/src/main/resources/cassandra/schema-keyspace.cql
Normal file
21
dao/src/main/resources/cassandra/schema-keyspace.cql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
--
|
||||||
|
-- Copyright © 2016-2022 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.
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE KEYSPACE IF NOT EXISTS thingsboard
|
||||||
|
WITH replication = {
|
||||||
|
'class' : 'SimpleStrategy',
|
||||||
|
'replication_factor' : 1
|
||||||
|
};
|
||||||
@ -14,12 +14,6 @@
|
|||||||
-- limitations under the License.
|
-- limitations under the License.
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE KEYSPACE IF NOT EXISTS thingsboard
|
|
||||||
WITH replication = {
|
|
||||||
'class' : 'SimpleStrategy',
|
|
||||||
'replication_factor' : 1
|
|
||||||
};
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS thingsboard.ts_kv_latest_cf (
|
CREATE TABLE IF NOT EXISTS thingsboard.ts_kv_latest_cf (
|
||||||
entity_type text, // (DEVICE, CUSTOMER, TENANT)
|
entity_type text, // (DEVICE, CUSTOMER, TENANT)
|
||||||
entity_id timeuuid,
|
entity_id timeuuid,
|
||||||
|
|||||||
@ -14,12 +14,6 @@
|
|||||||
-- limitations under the License.
|
-- limitations under the License.
|
||||||
--
|
--
|
||||||
|
|
||||||
CREATE KEYSPACE IF NOT EXISTS thingsboard
|
|
||||||
WITH replication = {
|
|
||||||
'class' : 'SimpleStrategy',
|
|
||||||
'replication_factor' : 1
|
|
||||||
};
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS thingsboard.ts_kv_cf (
|
CREATE TABLE IF NOT EXISTS thingsboard.ts_kv_cf (
|
||||||
entity_type text, // (DEVICE, CUSTOMER, TENANT)
|
entity_type text, // (DEVICE, CUSTOMER, TENANT)
|
||||||
entity_id timeuuid,
|
entity_id timeuuid,
|
||||||
|
|||||||
@ -33,6 +33,7 @@ public class NoSqlDaoServiceTestSuite {
|
|||||||
public static CustomCassandraCQLUnit cassandraUnit =
|
public static CustomCassandraCQLUnit cassandraUnit =
|
||||||
new CustomCassandraCQLUnit(
|
new CustomCassandraCQLUnit(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
|
new ClassPathCQLDataSet("cassandra/schema-keyspace.cql", false, false),
|
||||||
new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false),
|
new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false),
|
||||||
new ClassPathCQLDataSet("cassandra/schema-ts-latest.cql", false, false)
|
new ClassPathCQLDataSet("cassandra/schema-ts-latest.cql", false, false)
|
||||||
),
|
),
|
||||||
|
|||||||
@ -63,7 +63,7 @@ Tool execution time depends on DB size, CPU resources and Disk throughput
|
|||||||
* Note that this this part works only for single node Cassandra Cluster. If you have more nodes - it is better to use `sstableloader` tool.
|
* Note that this this part works only for single node Cassandra Cluster. If you have more nodes - it is better to use `sstableloader` tool.
|
||||||
|
|
||||||
1. [Optional] install Cassandra on the instance
|
1. [Optional] install Cassandra on the instance
|
||||||
2. [Optional] Using `cqlsh` create `thingsboard` keyspace and requred tables from this files `schema-ts.cql` and `schema-ts-latest.cql` using `source` command
|
2. [Optional] Using `cqlsh` create `thingsboard` keyspace and requred tables from this files `schema-keyspace.cql`, `schema-ts.cql` and `schema-ts-latest.cql` using `source` command
|
||||||
3. Stop Cassandra
|
3. Stop Cassandra
|
||||||
4. Look at `/var/lib/cassandra/data/thingsboard` and check for names of data folders
|
4. Look at `/var/lib/cassandra/data/thingsboard` and check for names of data folders
|
||||||
5. Copy generated SSTable files into cassandra data dir using next command:
|
5. Copy generated SSTable files into cassandra data dir using next command:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user