Docker compose scripts for TB Version Control Executor
This commit is contained in:
parent
dbec05a2c1
commit
4f2e1a25fd
@ -50,10 +50,8 @@ public interface EntitiesVersionControlService {
|
||||
|
||||
ListenableFuture<List<VersionedEntityInfo>> listAllEntitiesAtVersion(TenantId tenantId, String branch, String versionId) throws Exception;
|
||||
|
||||
|
||||
ListenableFuture<List<VersionLoadResult>> loadEntitiesVersion(SecurityUser user, VersionLoadRequest request) throws Exception;
|
||||
|
||||
|
||||
ListenableFuture<List<String>> listBranches(TenantId tenantId) throws Exception;
|
||||
|
||||
EntitiesVersionControlSettings getVersionControlSettings(TenantId tenantId);
|
||||
|
||||
@ -54,7 +54,7 @@ public class HashPartitionService implements PartitionService {
|
||||
private String coreTopic;
|
||||
@Value("${queue.core.partitions:100}")
|
||||
private Integer corePartitions;
|
||||
@Value("${queue.vc.topic}")
|
||||
@Value("${queue.vc.topic:tb_version_control}")
|
||||
private String vcTopic;
|
||||
@Value("${queue.vc.partitions:10}")
|
||||
private Integer vcPartitions;
|
||||
|
||||
@ -188,8 +188,9 @@ public class DefaultClusterVersionControlService extends TbApplicationEventListe
|
||||
ToVersionControlServiceMsg msg = msgWrapper.getValue();
|
||||
var ctx = new VersionControlRequestCtx(msg, msg.hasClearRepositoryRequest() ? null : getEntitiesVersionControlSettings(msg));
|
||||
long startTs = System.currentTimeMillis();
|
||||
log.trace("[{}][{}] Submitting task.", ctx.getTenantId(), ctx.getRequestId());
|
||||
ListenableFuture<Void> future = ioThreads.get(ctx.getTenantId().hashCode() % ioPoolSize).submit(() -> processMessage(ctx, msg));
|
||||
log.trace("[{}][{}] RECEIVED task: {}", ctx.getTenantId(), ctx.getRequestId(), msg);
|
||||
int threadIdx = Math.abs(ctx.getTenantId().hashCode() % ioPoolSize);
|
||||
ListenableFuture<Void> future = ioThreads.get(threadIdx).submit(() -> processMessage(ctx, msg));
|
||||
logTaskExecution(ctx, future, startTs);
|
||||
futures.add(future);
|
||||
}
|
||||
@ -435,13 +436,17 @@ public class DefaultClusterVersionControlService extends TbApplicationEventListe
|
||||
.setRequestIdMSB(ctx.getRequestId().getMostSignificantBits())
|
||||
.setRequestIdLSB(ctx.getRequestId().getLeastSignificantBits());
|
||||
if (e.isPresent()) {
|
||||
log.debug("[{}][{}] Failed to process task", ctx.getTenantId(), ctx.getRequestId(), e.get());
|
||||
builder.setError(e.get().getMessage());
|
||||
}
|
||||
} else {
|
||||
if (enrichFunction != null) {
|
||||
builder = enrichFunction.apply(builder);
|
||||
} else {
|
||||
builder.setGenericResponse(TransportProtos.GenericRepositoryResponseMsg.newBuilder().build());
|
||||
}
|
||||
log.debug("[{}][{}] Processed task", ctx.getTenantId(), ctx.getRequestId());
|
||||
}
|
||||
|
||||
ToCoreNotificationMsg msg = ToCoreNotificationMsg.newBuilder().setVcResponseMsg(builder).build();
|
||||
log.trace("[{}][{}] PUSHING reply: {} to: {}", ctx.getTenantId(), ctx.getRequestId(), msg, tpi);
|
||||
producer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
|
||||
|
||||
@ -10,6 +10,7 @@ HTTP_TRANSPORT_DOCKER_NAME=tb-http-transport
|
||||
COAP_TRANSPORT_DOCKER_NAME=tb-coap-transport
|
||||
LWM2M_TRANSPORT_DOCKER_NAME=tb-lwm2m-transport
|
||||
SNMP_TRANSPORT_DOCKER_NAME=tb-snmp-transport
|
||||
TB_VC_EXECUTOR_DOCKER_NAME=tb-vc-executor
|
||||
|
||||
TB_VERSION=latest
|
||||
|
||||
|
||||
1
docker/.gitignore
vendored
1
docker/.gitignore
vendored
@ -5,4 +5,5 @@ tb-node/db/**
|
||||
tb-node/postgres/**
|
||||
tb-node/cassandra/**
|
||||
tb-transports/*/log
|
||||
tb-vc-executor/log/**
|
||||
!.env
|
||||
|
||||
@ -61,3 +61,9 @@ services:
|
||||
tb-snmp-transport:
|
||||
env_file:
|
||||
- queue-confluent.env
|
||||
tb-vc-executor1:
|
||||
env_file:
|
||||
- queue-confluent.env
|
||||
tb-vc-executor2:
|
||||
env_file:
|
||||
- queue-confluent.env
|
||||
|
||||
@ -90,3 +90,13 @@ services:
|
||||
- queue-kafka.env
|
||||
depends_on:
|
||||
- kafka
|
||||
tb-vc-executor1:
|
||||
env_file:
|
||||
- queue-kafka.env
|
||||
depends_on:
|
||||
- kafka
|
||||
tb-vc-executor2:
|
||||
env_file:
|
||||
- queue-kafka.env
|
||||
depends_on:
|
||||
- kafka
|
||||
@ -53,6 +53,13 @@ services:
|
||||
tb-snmp-transport:
|
||||
volumes:
|
||||
- tb-snmp-transport-log-volume:/var/log/tb-snmp-transport
|
||||
tb-vc-executor1:
|
||||
volumes:
|
||||
- tb-vc-executor-log-volume:/var/log/tb-vc-executor
|
||||
tb-vc-executor2:
|
||||
volumes:
|
||||
- tb-vc-executor-log-volume:/var/log/tb-vc-executor
|
||||
|
||||
|
||||
volumes:
|
||||
postgres-db-volume:
|
||||
@ -76,3 +83,6 @@ volumes:
|
||||
tb-snmp-transport-log-volume:
|
||||
external: true
|
||||
name: ${TB_SNMP_TRANSPORT_LOG_VOLUME}
|
||||
tb-vc-executor-log-volume:
|
||||
external: true
|
||||
name: ${TB_VC_EXECUTOR_LOG_VOLUME}
|
||||
@ -23,59 +23,40 @@ services:
|
||||
tb-core1:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-core2:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-rule-engine1:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-rule-engine2:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-mqtt-transport1:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-mqtt-transport2:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-http-transport1:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-http-transport2:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-coap-transport:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-lwm2m-transport:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-snmp-transport:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-vc-executor1:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
tb-vc-executor2:
|
||||
env_file:
|
||||
- queue-pubsub.env
|
||||
|
||||
|
||||
@ -23,59 +23,39 @@ services:
|
||||
tb-core1:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-core2:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-rule-engine1:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-rule-engine2:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-mqtt-transport1:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-mqtt-transport2:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-http-transport1:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-http-transport2:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-coap-transport:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-lwm2m-transport:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-snmp-transport:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-vc-executor1:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
tb-vc-executor2:
|
||||
env_file:
|
||||
- queue-rabbitmq.env
|
||||
@ -23,57 +23,39 @@ services:
|
||||
tb-core1:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-core2:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-rule-engine1:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-rule-engine2:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- redis
|
||||
tb-mqtt-transport1:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-mqtt-transport2:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-http-transport1:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-http-transport2:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-coap-transport:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
tb-lwm2m-transport:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-snmp-transport:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
depends_on:
|
||||
- zookeeper
|
||||
tb-vc-executor1:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
tb-vc-executor2:
|
||||
env_file:
|
||||
- queue-service-bus.env
|
||||
|
||||
@ -257,6 +257,38 @@ services:
|
||||
- "8080"
|
||||
env_file:
|
||||
- tb-web-ui.env
|
||||
tb-vc-executor1:
|
||||
restart: always
|
||||
image: "${DOCKER_REPO}/${TB_VC_EXECUTOR_DOCKER_NAME}:${TB_VERSION}"
|
||||
ports:
|
||||
- "8081"
|
||||
environment:
|
||||
TB_SERVICE_ID: tb-vc-executor1
|
||||
env_file:
|
||||
- tb-vc-executor.env
|
||||
volumes:
|
||||
- ./tb-vc-executor/conf:/config
|
||||
- ./tb-vc-executor/log:/var/log/tb-vc-executor
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- tb-core1
|
||||
- tb-core2
|
||||
tb-vc-executor2:
|
||||
restart: always
|
||||
image: "${DOCKER_REPO}/${TB_VC_EXECUTOR_DOCKER_NAME}:${TB_VERSION}"
|
||||
ports:
|
||||
- "8081"
|
||||
environment:
|
||||
TB_SERVICE_ID: tb-vc-executor2
|
||||
env_file:
|
||||
- tb-vc-executor.env
|
||||
volumes:
|
||||
- ./tb-vc-executor/conf:/config
|
||||
- ./tb-vc-executor/log:/var/log/tb-vc-executor
|
||||
depends_on:
|
||||
- zookeeper
|
||||
- tb-core1
|
||||
- tb-core2
|
||||
haproxy:
|
||||
restart: always
|
||||
container_name: "${LOAD_BALANCER_NAME}"
|
||||
|
||||
@ -26,3 +26,5 @@ mkdir -p tb-transports/http/log && sudo chown -R 799:799 tb-transports/http/log
|
||||
mkdir -p tb-transports/mqtt/log && sudo chown -R 799:799 tb-transports/mqtt/log
|
||||
|
||||
mkdir -p tb-transports/snmp/log && sudo chown -R 799:799 tb-transports/snmp/log
|
||||
|
||||
mkdir -p tb-vc-executor/log && sudo chown -R 799:799 tb-vc-executor/log
|
||||
|
||||
2
docker/tb-vc-executor.env
Normal file
2
docker/tb-vc-executor.env
Normal file
@ -0,0 +1,2 @@
|
||||
ZOOKEEPER_ENABLED=true
|
||||
ZOOKEEPER_URL=zookeeper:2181
|
||||
51
docker/tb-vc-executor/conf/logback.xml
Normal file
51
docker/tb-vc-executor/conf/logback.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<!DOCTYPE configuration>
|
||||
<configuration scan="true" scanPeriod="10 seconds">
|
||||
|
||||
<appender name="fileLogAppender"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>/var/log/tb-vc-executor/${TB_SERVICE_ID}/tb-vc-executor.log</file>
|
||||
<rollingPolicy
|
||||
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>/var/log/tb-vc-executor/${TB_SERVICE_ID}/tb-vc-executor.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>30</maxHistory>
|
||||
<totalSizeCap>3GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.thingsboard.server.queue" level="INFO" />
|
||||
<logger name="org.thingsboard.server" level="TRACE" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="fileLogAppender"/>
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
23
docker/tb-vc-executor/conf/tb-vc-executor.conf
Normal file
23
docker/tb-vc-executor/conf/tb-vc-executor.conf
Normal file
@ -0,0 +1,23 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*,heap*,age*,safepoint=debug:file=/var/log/tb-vc-executor/${TB_SERVICE_ID}-gc.log:time,uptime,level,tags:filecount=10,filesize=10M"
|
||||
export JAVA_OPTS="$JAVA_OPTS -XX:+IgnoreUnrecognizedVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/tb-vc-executor/${TB_SERVICE_ID}-heapdump.bin"
|
||||
export JAVA_OPTS="$JAVA_OPTS -XX:-UseBiasedLocking -XX:+UseTLAB -XX:+ResizeTLAB -XX:+PerfDisableSharedMem -XX:+UseCondCardMark"
|
||||
export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=500 -XX:+UseStringDeduplication -XX:+ParallelRefProcEnabled -XX:MaxTenuringThreshold=10"
|
||||
export JAVA_OPTS="$JAVA_OPTS -XX:+ExitOnOutOfMemoryError"
|
||||
export LOG_FILENAME=tb-vc-executor.out
|
||||
export LOADER_PATH=/usr/share/tb-vc-executor/conf
|
||||
@ -34,6 +34,7 @@ public class ThingsBoardDbInstaller extends ExternalResource {
|
||||
private final static String TB_HTTP_TRANSPORT_LOG_VOLUME = "tb-http-transport-log-test-volume";
|
||||
private final static String TB_MQTT_TRANSPORT_LOG_VOLUME = "tb-mqtt-transport-log-test-volume";
|
||||
private final static String TB_SNMP_TRANSPORT_LOG_VOLUME = "tb-snmp-transport-log-test-volume";
|
||||
private final static String TB_VC_EXECUTOR_LOG_VOLUME = "tb-vc-executor-log-test-volume";
|
||||
|
||||
private final DockerComposeExecutor dockerCompose;
|
||||
|
||||
@ -44,6 +45,7 @@ public class ThingsBoardDbInstaller extends ExternalResource {
|
||||
private final String tbHttpTransportLogVolume;
|
||||
private final String tbMqttTransportLogVolume;
|
||||
private final String tbSnmpTransportLogVolume;
|
||||
private final String tbVcExecutorLogVolume;
|
||||
private final Map<String, String> env;
|
||||
|
||||
public ThingsBoardDbInstaller() {
|
||||
@ -61,6 +63,7 @@ public class ThingsBoardDbInstaller extends ExternalResource {
|
||||
tbHttpTransportLogVolume = project + "_" + TB_HTTP_TRANSPORT_LOG_VOLUME;
|
||||
tbMqttTransportLogVolume = project + "_" + TB_MQTT_TRANSPORT_LOG_VOLUME;
|
||||
tbSnmpTransportLogVolume = project + "_" + TB_SNMP_TRANSPORT_LOG_VOLUME;
|
||||
tbVcExecutorLogVolume = project + "_" + TB_VC_EXECUTOR_LOG_VOLUME;
|
||||
|
||||
dockerCompose = new DockerComposeExecutor(composeFiles, project);
|
||||
|
||||
@ -72,6 +75,7 @@ public class ThingsBoardDbInstaller extends ExternalResource {
|
||||
env.put("TB_HTTP_TRANSPORT_LOG_VOLUME", tbHttpTransportLogVolume);
|
||||
env.put("TB_MQTT_TRANSPORT_LOG_VOLUME", tbMqttTransportLogVolume);
|
||||
env.put("TB_SNMP_TRANSPORT_LOG_VOLUME", tbSnmpTransportLogVolume);
|
||||
env.put("TB_VC_EXECUTOR_LOG_VOLUME", tbVcExecutorLogVolume);
|
||||
dockerCompose.withEnv(env);
|
||||
}
|
||||
|
||||
@ -104,6 +108,9 @@ public class ThingsBoardDbInstaller extends ExternalResource {
|
||||
dockerCompose.withCommand("volume create " + tbSnmpTransportLogVolume);
|
||||
dockerCompose.invokeDocker();
|
||||
|
||||
dockerCompose.withCommand("volume create " + tbVcExecutorLogVolume);
|
||||
dockerCompose.invokeDocker();
|
||||
|
||||
dockerCompose.withCommand("up -d redis postgres");
|
||||
dockerCompose.invokeCompose();
|
||||
|
||||
@ -126,10 +133,11 @@ public class ThingsBoardDbInstaller extends ExternalResource {
|
||||
copyLogs(tbHttpTransportLogVolume, "./target/tb-http-transport-logs/");
|
||||
copyLogs(tbMqttTransportLogVolume, "./target/tb-mqtt-transport-logs/");
|
||||
copyLogs(tbSnmpTransportLogVolume, "./target/tb-snmp-transport-logs/");
|
||||
copyLogs(tbVcExecutorLogVolume, "./target/tb-vc-executor-logs/");
|
||||
|
||||
dockerCompose.withCommand("volume rm -f " + postgresDataVolume + " " + tbLogVolume +
|
||||
" " + tbCoapTransportLogVolume + " " + tbLwm2mTransportLogVolume + " " + tbHttpTransportLogVolume +
|
||||
" " + tbMqttTransportLogVolume + " " + tbSnmpTransportLogVolume);
|
||||
" " + tbMqttTransportLogVolume + " " + tbSnmpTransportLogVolume + " " + tbVcExecutorLogVolume);
|
||||
dockerCompose.invokeDocker();
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,9 @@ FROM thingsboard/openjdk11
|
||||
|
||||
COPY start-tb-vc-executor.sh ${pkg.name}.deb /tmp/
|
||||
|
||||
RUN mkdir -p /home/thingsboard/.config/jgit
|
||||
RUN chown -R ${pkg.user}:${pkg.user} /home/thingsboard
|
||||
|
||||
RUN chmod a+x /tmp/*.sh \
|
||||
&& mv /tmp/start-tb-vc-executor.sh /usr/bin
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user