Enable dynamodb global-refdb

Remove zookeeper refdb and replace it with dynamodb also taking care of
creating the relevant DynamoDB tables on request.

The DynamoDB refdb is now used for both multi-site and high-availability
plugin.

Bug: Issue 15127
Change-Id: I5012c15ae2c06ecc55cc2693fc516ce34842a58e
diff --git a/.gitignore b/.gitignore
index bec44c7..0bf1d7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,5 @@
 gerrit.config
 secure.config
 replication.config
-zookeeper-refdb.config
 .idea
 **/*.pem
diff --git a/Makefile.common b/Makefile.common
index 05f6679..371001e 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -23,6 +23,7 @@
 	aws s3 cp ../common-templates/cf-primary-asg.yml s3://$(TEMPLATE_BUCKET_NAME)/
 	aws s3 cp ../common-templates/cf-efs-stack.yml s3://$(TEMPLATE_BUCKET_NAME)/
 	aws s3 cp ../common-templates/cf-ecs-service-cpu-autoscaling.yml s3://$(TEMPLATE_BUCKET_NAME)/
+	aws s3 cp ../common-templates/cf-dynamodb-stack.yml s3://$(TEMPLATE_BUCKET_NAME)/
 
 set-optional-params-metrics-cloudwatch:
 ifdef METRICS_CLOUDWATCH_ENABLED
@@ -62,10 +63,6 @@
 ifdef MULTISITE_ENABLED
 		$(eval MULTISITE_OPTIONAL_PARAMS := ParameterKey=MultiSiteEnabled,ParameterValue=$(MULTISITE_ENABLED))
 		$(eval MULTISITE_OPTIONAL_PARAMS := $(MULTISITE_OPTIONAL_PARAMS) ParameterKey=MultiSiteKafkaBrokers,ParameterValue=\"$(MULTISITE_KAFKA_BROKERS)\")
-		$(eval MULTISITE_OPTIONAL_PARAMS := $(MULTISITE_OPTIONAL_PARAMS) ParameterKey=MultiSiteZookeeperConnectString,ParameterValue=$(MULTISITE_ZOOKEEPER_CONNECT_STRING))
-endif
-ifdef MULTISITE_ZOOKEEPER_ROOT_NODE
-		$(eval MULTISITE_OPTIONAL_PARAMS := $(MULTISITE_OPTIONAL_PARAMS) ParameterKey=MultiSiteZookeeperRootNode,ParameterValue=$(MULTISITE_ZOOKEEPER_ROOT_NODE))
 endif
 
 set-ldap-account-pattern:
diff --git a/common-templates/cf-dynamodb-stack.yml b/common-templates/cf-dynamodb-stack.yml
new file mode 100644
index 0000000..7494aac
--- /dev/null
+++ b/common-templates/cf-dynamodb-stack.yml
@@ -0,0 +1,60 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Description: DynamoDB tables for refs-db validation
+Parameters:
+  DynamoDBLocksTableName:
+    Description: The name of the DynamoDB locks table
+    Type: String
+  DynamoDBRefsTableName:
+    Description: The name of the DynamoDB refs table
+    Type: String
+
+Mappings:
+  DynamoDB:
+    CapacityUnits:
+      Read: 10
+      Write: 10
+
+Resources:
+  RefsDbTable:
+    Type: AWS::DynamoDB::Table
+    Properties:
+      TableName: !Ref DynamoDBRefsTableName
+      AttributeDefinitions:
+        - AttributeName: refPath
+          AttributeType: S
+      KeySchema:
+        - AttributeName: refPath
+          KeyType: HASH
+      ProvisionedThroughput:
+        ReadCapacityUnits: !FindInMap ['DynamoDB', 'CapacityUnits', 'Read']
+        WriteCapacityUnits: !FindInMap ['DynamoDB', 'CapacityUnits', 'Write']
+
+  LocksTable:
+    Type: AWS::DynamoDB::Table
+    Properties:
+      TableName: !Ref DynamoDBLocksTableName
+      AttributeDefinitions:
+        - AttributeName: lockKey
+          AttributeType: S
+        - AttributeName: lockValue
+          AttributeType: S
+      KeySchema:
+        - AttributeName: lockKey
+          KeyType: HASH
+        - AttributeName: lockValue
+          KeyType: RANGE
+      ProvisionedThroughput:
+        ReadCapacityUnits: !FindInMap ['DynamoDB', 'CapacityUnits', 'Read']
+        WriteCapacityUnits: !FindInMap ['DynamoDB', 'CapacityUnits', 'Write']
+
+Outputs:
+  RefsDbTable:
+    Description: The refs-db table
+    Value: !Ref RefsDbTable
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'RefsDbTable' ] ]
+  LocksTable:
+    Description: The locks-db table
+    Value: !Ref LocksTable
+    Export:
+      Name: !Join [ ':', [ !Ref 'AWS::StackName', 'LocksTable' ] ]
\ No newline at end of file
diff --git a/common-templates/cf-gerrit-task-execution-role.yml b/common-templates/cf-gerrit-task-execution-role.yml
index 65c0fc7..2c748d0 100644
--- a/common-templates/cf-gerrit-task-execution-role.yml
+++ b/common-templates/cf-gerrit-task-execution-role.yml
@@ -31,6 +31,17 @@
                   - 'logs:PutLogEvents'
                   # Allow the ECS tasks to push metrics to CloudWatch
                   - 'cloudwatch:PutMetricData'
+                  # Allow the ECS tasks to perform CRUD actions to dynamodb table:
+                  # Used for global refs-db operations.
+                  - 'dynamodb:DeleteItem'
+                  - 'dynamodb:CreateTable'
+                  - 'dynamodb:DescribeTable'
+                  - 'dynamodb:GetItem'
+                  - 'dynamodb:ListTables'
+                  - 'dynamodb:PutItem'
+                  - 'dynamodb:Query'
+                  - 'dynamodb:Scan'
+                  - 'dynamodb:UpdateItem'
                 Resource: '*'
           - PolicyName: AmazonECSTaskSecretManagerRolePolicy
             PolicyDocument:
diff --git a/dual-primary/Makefile b/dual-primary/Makefile
index 9007fe5..c61e8d0 100644
--- a/dual-primary/Makefile
+++ b/dual-primary/Makefile
@@ -15,7 +15,10 @@
 
 SINGLE_SITE_PLUGINS=javamelody high-availability healthcheck metrics-reporter-cloudwatch
 
-MULTI_SITE_PLUGINS=$(SINGLE_SITE_PLUGINS) multi-site kafka-events websession-broker zookeeper-refdb~zk-3.5
+HA_SITE_PLUGINS=$(SINGLE_SITE_PLUGINS) aws-dynamodb-refdb
+HA_SITE_PLUGINS_LIBS_LINKS=high-availability
+
+MULTI_SITE_PLUGINS=$(SINGLE_SITE_PLUGINS) multi-site kafka-events websession-broker
 MULTI_SITE_PLUGINS_LIBS_LINKS=multi-site replication
 MULTI_SITE_MAVEN_LIBS=events-broker~$(EVENTSBROKER_LIB_VER)
 
@@ -54,7 +57,8 @@
 			set-optional-params-for-replica-filesystem \
 			set-optional-params-for-replica-auto-scaling-capacity \
 			set-optional-params-for-replica-capacity-provider \
-			set-optional-network-params
+			set-optional-network-params \
+			set-optional-refs-db-params
 ifdef CLUSTER_INSTANCE_TYPE
 		$(eval CLUSTER_OPTIONAL_PARAMS := $(CLUSTER_OPTIONAL_PARAMS) ParameterKey=InstanceType,ParameterValue=$(CLUSTER_INSTANCE_TYPE))
 endif
@@ -79,6 +83,9 @@
 ifdef LOAD_BALANCER_SCHEME
 		$(eval CLUSTER_OPTIONAL_PARAMS := $(CLUSTER_OPTIONAL_PARAMS) ParameterKey=PrimariesGerritLoadBalancerScheme,ParameterValue=$(LOAD_BALANCER_SCHEME))
 endif
+ifdef CREATE_REFS_DB_TABLES
+		$(eval CLUSTER_OPTIONAL_PARAMS := $(CLUSTER_OPTIONAL_PARAMS) ParameterKey=CreateRefsDBTables,ParameterValue=$(CREATE_REFS_DB_TABLES))
+endif
 
 	$(AWS_FC_COMMAND) create-stack \
 		--stack-name $(CLUSTER_STACK_NAME) \
@@ -94,12 +101,14 @@
 		$(GERRIT_OPTIONAL_PRIMARY_VOLUME) \
 		$(GERRIT_OPTIONAL_PARAMS_REPLICA_FILESYSTEM) \
 		$(GERRIT_OPTIONAL_PARAMS_REPLICA_AUTO_SCALING_CAPACITY) \
-		$(GERRIT_OPTIONAL_PARAMS_REPLICA_CAPACITY_PROVIDER)
+		$(GERRIT_OPTIONAL_PARAMS_REPLICA_CAPACITY_PROVIDER) \
+		$(REFS_DB_OPTIONAL_PARAMS)
 
 service-primary-1: set-optional-params-metrics-cloudwatch set-optional-params-smtp \
 					set-optional-params-multisite set-ldap-account-pattern \
 					set-optional-gerrit-ulimits set-optional-jgit-conf \
-					set-high-availability-optional-params
+					set-high-availability-optional-params \
+					set-optional-refs-db-params
 ifdef GERRIT_PRIMARY1_INSTANCE_ID
 		$(eval PRIMARY1_SERVICE_OPTIONAL_PARAMS := $(PRIMARY1_SERVICE_OPTIONAL_PARAMS) ParameterKey=InstanceId,ParameterValue=$(GERRIT_PRIMARY1_INSTANCE_ID))
 endif
@@ -150,12 +159,14 @@
 		$(LDAP_ACCOUNT_PATTERN_PARAM) \
 		$(METRICS_CW_OPTIONAL_PARAMS) \
 		$(SMTP_OPTIONAL_PARAMS) \
-		$(GERRIT_ULIMITS)
+		$(GERRIT_ULIMITS) \
+		$(REFS_DB_OPTIONAL_PARAMS)
 
 service-primary-2: set-optional-params-metrics-cloudwatch set-optional-params-smtp \
 					set-optional-params-multisite set-ldap-account-pattern \
 					set-optional-gerrit-ulimits set-optional-jgit-conf \
-					set-high-availability-optional-params
+					set-high-availability-optional-params \
+					set-optional-refs-db-params
 ifdef GERRIT_PRIMARY2_INSTANCE_ID
 		$(eval PRIMARY2_SERVICE_OPTIONAL_PARAMS := $(PRIMARY2_SERVICE_OPTIONAL_PARAMS) ParameterKey=InstanceId,ParameterValue=$(GERRIT_PRIMARY2_INSTANCE_ID))
 endif
@@ -207,7 +218,8 @@
 		$(LDAP_ACCOUNT_PATTERN_PARAM) \
 		$(METRICS_CW_OPTIONAL_PARAMS) \
 		$(SMTP_OPTIONAL_PARAMS) \
-		$(GERRIT_ULIMITS)
+		$(GERRIT_ULIMITS) \
+		$(REFS_DB_OPTIONAL_PARAMS)
 
 service-replication:
 	$(AWS_FC_COMMAND) create-stack \
@@ -498,7 +510,7 @@
 						$(optional_git_gc_targets_deletion) \
 						delete-cluster wait-for-cluster-deletion
 
-delete-all-including-retained-stack: confirm-persistent-stack-deletion delete-all delete-git-primary-persistent-stack delete-git-replica-persistent-stack delete-network-persistent-stack
+delete-all-including-retained-stack: confirm-persistent-stack-deletion delete-all delete-git-primary-persistent-stack delete-git-replica-persistent-stack delete-network-persistent-stack delete-dynamodb-persistent-stack
 
 delete-git-primary-persistent-stack:
 
@@ -521,7 +533,7 @@
 ifeq ($(MULTISITE_ENABLED),true)
 	$(MAKE) -C ../gerrit gerrit-publish RECIPE=dual-primary PLUGINS="$(MULTI_SITE_PLUGINS)" PLUGINS_LIBS_LINKS="$(MULTI_SITE_PLUGINS_LIBS_LINKS)" MAVEN_LIBS="$(MULTI_SITE_MAVEN_LIBS)"
 else
-	$(MAKE) -C ../gerrit gerrit-publish RECIPE=dual-primary PLUGINS="$(SINGLE_SITE_PLUGINS)"
+	$(MAKE) -C ../gerrit gerrit-publish RECIPE=dual-primary PLUGINS="$(HA_SITE_PLUGINS)" PLUGINS_LIBS_LINKS="$(HA_SITE_PLUGINS_LIBS_LINKS)"
 endif
 
 haproxy-publish:
@@ -541,3 +553,28 @@
 ifdef AUTOREINDEX_POLL_INTERVAL
 		$(eval HA_OPTIONAL_PARAMS := ParameterKey=AutoReindexPollInterval,ParameterValue=$(AUTOREINDEX_POLL_INTERVAL))
 endif
+
+set-optional-refs-db-params:
+	$(eval REFS_DB_OPTIONAL_PARAMS=)
+ifdef DYNAMODB_LOCKS_TABLE_NAME
+		$(eval REFS_DB_OPTIONAL_PARAMS := $(REFS_DB_OPTIONAL_PARAMS) ParameterKey=DynamoDBLocksTableName,ParameterValue=$(DYNAMODB_LOCKS_TABLE_NAME))
+endif
+ifdef DYNAMODB_REFS_TABLE_NAME
+		$(eval REFS_DB_OPTIONAL_PARAMS := $(REFS_DB_OPTIONAL_PARAMS) ParameterKey=DynamoDBRefsTableName,ParameterValue=$(DYNAMODB_REFS_TABLE_NAME))
+endif
+
+delete-dynamodb-persistent-stack:
+	$(eval DYNAMODB_STACK_NAME=$(shell $(AWS_FC_COMMAND) list-stacks --stack-status-filter CREATE_COMPLETE --query "StackSummaries[*].StackName" | jq -r '.[]| select(startswith("$(CLUSTER_STACK_NAME)-DynamoDBPersistentStack"))'))
+
+	$(if $(DYNAMODB_STACK_NAME), \
+		$(AWS_FC_COMMAND) delete-stack \
+			--stack-name $(DYNAMODB_STACK_NAME) \
+			--region $(AWS_REGION) && \
+		echo "*** Wait for DynamoDB stack '$(DYNAMODB_STACK_NAME)' deletion" && \
+		$(AWS_FC_COMMAND) wait stack-delete-complete \
+			--stack-name $(DYNAMODB_STACK_NAME) \
+			--region $(AWS_REGION) && \
+		echo "*** DynamoDB stack '$(DYNAMODB_STACK_NAME)' deleted" \
+		, \
+		echo "No DynamoDB stack found. Nothing to do." \
+	)
\ No newline at end of file
diff --git a/dual-primary/README.md b/dual-primary/README.md
index f08f391..1155491 100644
--- a/dual-primary/README.md
+++ b/dual-primary/README.md
@@ -98,6 +98,10 @@
 SUBNET2_CIDR=10.0.32.0/24
 ```
 
+Note that if the refs-db dynamodb tables were created as part of the initial
+stack (`CREATE_REFS_DB_TABLES` was set to `true`), you will need to explicitly
+set it to `false` to avoid attempting to create the same tables again.
+
 3. Deploy the *green* stack:
 
 ```bash
@@ -211,6 +215,19 @@
 Default: `10m`
 high-availability docs [here](https://gerrit.googlesource.com/plugins/high-availability/+/refs/heads/master/src/main/resources/Documentation/config.md)
 
+* `DYNAMODB_LOCKS_TABLE_NAME`. Optional. The name of the dynamoDB table used to
+  store distribute locking.
+  Default: `locksTable`
+  See DynamoDB lock client [here](https://github.com/awslabs/amazon-dynamodb-lock-client)
+
+* `DYNAMODB_REFS_TABLE_NAME`. Optional. The name of the dynamoDB table used to
+  store git refs and their associated sha1.
+  Default: `refsDb`
+
+* `CREATE_REFS_DB_TABLES`. Optional. Whether to create the DynamoDB refs and
+  lock tables.
+  Default: `false`
+
 ##### Shared filesystem for replicas
 
 Similarly to primary nodes, replicas share a data via an EFS filesystem which is
@@ -356,7 +373,7 @@
 for more information on this.
 
 ##### Requirements
-* Kafka brokers and Zookeeper are required by this recipe and are expected to exist
+* Kafka brokers and DynamoDB are required by this recipe and are expected to exist
 and accessible with server-side TLS security enabled by the primary instances
 resulting from the deployment of this recipe.
 * Replication service must be enabled to allow syncing of Git data.
@@ -365,15 +382,9 @@
 
 * `MULTISITE_ENABLED`: Optional. Whether this Gerrit is part of a multi-site
 cluster deployment. "false" by default.
-* `MULTISITE_ZOOKEEPER_CONNECT_STRING`: Required when "MULTISITE_ENABLED=true".
-Connection string to Zookeeper.
 * `MULTISITE_KAFKA_BROKERS`: Required when "MULTISITE_ENABLED=true".
 Comma separated list of Kafka broker hosts (host:port)
 to use for publishing events to the message broker.
-* `MULTISITE_ZOOKEEPER_ROOT_NODE` Optional. Root node to use in Zookeeper to
-store/retrieve information.
-Constraint: a slash-separated ('/') string not starting with a slash ('/')
-"gerrit/multi-site" by default.
 * `MULTISITE_GLOBAL_PROJECTS`: Optional. Comma separated list of patterns (see [projects.pattern](https://gerrit.googlesource.com/plugins/multi-site/+/refs/heads/stable-3.2/src/main/resources/Documentation/config.md))
 to specify which projects are available across all sites. This parametes applies to both multi-site
 and replication service remote destinations.
@@ -433,10 +444,12 @@
 * EFS stack
 * VPC and subnets (if created as part of this deployment, rather than externally
 provided)
+* Refs-DB DynamoDB stack (if created as part of this deployment, rather than
+  externally provided))
 
 Note that you can completely delete the stack, including explicitly retained
-resources such as the EFS Git filesystem, VPC and subnets, by issuing the more
-aggressive command:
+resources such as the EFS Git filesystem, VPC and subnets and DynamoDB stack by
+issuing the more aggressive command:
 
 ```
 make [AWS_REGION=a-valid-aws-region] [AWS_PREFIX=some-cluster-prefix] delete-all-including-retained-stack
diff --git a/dual-primary/cf-cluster.yml b/dual-primary/cf-cluster.yml
index 620dd01..2560cd2 100644
--- a/dual-primary/cf-cluster.yml
+++ b/dual-primary/cf-cluster.yml
@@ -163,8 +163,22 @@
   PrimariesGerritCertificateArn:
     Description: SSL Certificates ARN for the load balancer serving requests to the primary gerrit instances
     Type: String
+  DynamoDBLocksTableName:
+    Description: The name of the DynamoDB locks table
+    Type: String
+    Default: 'locksTable'
+  DynamoDBRefsTableName:
+    Description: The name of the DynamoDB refs table
+    Type: String
+    Default: 'refsDb'
+  CreateRefsDBTables:
+    Description: Whether to create DynamoDB tables for refs-db
+    Type: String
+    Default: false
+    AllowedValues: [true, false]
 
 Conditions:
+  ShouldCreateDynamoDBTables: !Equals [!Ref CreateRefsDBTables, "true"]
   isProvisionedThroughput: !Equals [!Ref PrimaryFileSystemThroughputMode, "provisioned"]
   CreatePrimaryEFS: !Equals [!Ref PrimaryFileSystemID, ""]
   CreateReplicaEFS: !Equals [!Ref ReplicaFileSystemID, ""]
@@ -459,6 +473,9 @@
               - 'ecr:GetDownloadUrlForLayer'
               - 'ec2:AttachVolume'
               - 'ec2:DescribeVolumes'
+              - "dynamodb:CreateTable"
+              - "dynamodb:DeleteTable"
+              - "dynamodb:ListTables"
             Resource: '*'
 
   PrimaryGitFileSystemPermanentStack:
@@ -513,6 +530,17 @@
         Subnet2CIDR: !Ref 'Subnet2CIDR'
         Subnet2AZProp: !Ref 'Subnet2AZProp'
 
+  DynamoDBPersistentStack:
+    Type: AWS::CloudFormation::Stack
+    DeletionPolicy: Retain
+    Condition: ShouldCreateDynamoDBTables
+    Properties:
+      TemplateURL: !Join [ '', ['https://', !Ref TemplateBucketName, '.s3.amazonaws.com/cf-dynamodb-stack.yml'] ]
+      TimeoutInMinutes: '25'
+      Parameters:
+        DynamoDBRefsTableName: !Ref DynamoDBRefsTableName
+        DynamoDBLocksTableName: !Ref DynamoDBLocksTableName
+
 Outputs:
   ClusterName:
     Description: The name of the ECS cluster
diff --git a/dual-primary/cf-service-primary.yml b/dual-primary/cf-service-primary.yml
index d08c07a..d865835 100644
--- a/dual-primary/cf-service-primary.yml
+++ b/dual-primary/cf-service-primary.yml
@@ -172,16 +172,14 @@
     Description: Comma separated list of Kafka broker hosts (host:port) to use for publishing events to the message broker
     Type: CommaDelimitedList
     Default: ''
-  MultiSiteZookeeperConnectString:
-    Description: Connection string to Zookeeper
+  DynamoDBLocksTableName:
+    Description: The name of the DynamoDB locks table
     Type: String
-    Default: ''
-  MultiSiteZookeeperRootNode:
-    Description: Root node to use in Zookeeper to store/retrieve information
+    Default: 'locksTable'
+  DynamoDBRefsTableName:
+    Description: The name of the DynamoDB refs table
     Type: String
-    ConstraintDescription: Choose a slash-separated ('/') string not starting with a slash ('/')
-    AllowedPattern: '^[^\/].*'
-    Default: 'gerrit/multi-site'
+    Default: 'refsDb'
   AutoReindexPollInterval:
     Description: Interval between reindexing of all changes, accounts and groups.
     Type: String
@@ -334,10 +332,12 @@
                       Value: !Ref MultiSiteEnabled
                     - Name: MULTISITE_KAFKA_BROKERS
                       Value: !Join [',', !Ref MultiSiteKafkaBrokers]
-                    - Name: MULTISITE_ZOOKEEPER_CONNECT_STRING
-                      Value: !Ref MultiSiteZookeeperConnectString
-                    - Name: MULTISITE_ZOOKEEPER_ROOT_NODE
-                      Value: !Ref MultiSiteZookeeperRootNode
+                    - Name: REFS_DB_ENABLED
+                      Value: true
+                    - Name: DYNAMODB_LOCKS_TABLE_NAME
+                      Value: !Ref DynamoDBLocksTableName
+                    - Name: DYNAMODB_REFS_TABLE_NAME
+                      Value: !Ref DynamoDBRefsTableName
                   Ulimits:
                     - Name: nofile
                       HardLimit: !Ref FileDescriptorsHardLimit
diff --git a/dual-primary/setup.env.template b/dual-primary/setup.env.template
index c282ff6..b1314ed 100644
--- a/dual-primary/setup.env.template
+++ b/dual-primary/setup.env.template
@@ -1,7 +1,5 @@
 MULTISITE_ENABLED:=false
-MULTISITE_ZOOKEEPER_CONNECT_STRING:=zookeeper-yourcompany.com:2181
 MULTISITE_KAFKA_BROKERS:=kafka0-yourcompany.com:9092,kafka1-yourcompany.com:9092
-MULTISITE_ZOOKEEPER_ROOT_NODE:=gerrit/multi-site
 
 CLUSTER_INSTANCE_TYPE:=m4.2xlarge
 SERVICE_PRIMARY1_STACK_NAME:=$(AWS_PREFIX)-service-primary-1
@@ -97,4 +95,8 @@
 # Existing SUBNET2 settings
 SUBNET2_CIDR=
 SUBNET2_ID=
-SUBNET2_AZ=
\ No newline at end of file
+SUBNET2_AZ=
+
+DYNAMODB_LOCKS_TABLE_NAME=$(AWS_PREFIX)-locksTable
+DYNAMODB_REFS_TABLE_NAME=$(AWS_PREFIX)-refsDb
+CREATE_REFS_DB_TABLES=false
\ No newline at end of file
diff --git a/gerrit/entrypoint.sh b/gerrit/entrypoint.sh
index a5e1128..4aa5446 100755
--- a/gerrit/entrypoint.sh
+++ b/gerrit/entrypoint.sh
@@ -10,8 +10,8 @@
 
   echo "Ensure primary specific plugins and libraries are not installed:"
   for jar in "lib/multi-site.jar" "plugins/multi-site.jar" "lib/replication.jar" \
-    "lib/events-broker.jar" "plugins/kafka-events.jar" "plugins/zookeeper-refdb.jar" \
-    "plugins/websession-broker.jar" "plugins/high-availability.jar"
+    "lib/events-broker.jar" "plugins/kafka-events.jar" "plugins/aws-dynamodb-refdb.jar" \
+    "plugins/websession-broker.jar" "plugins/high-availability.jar" "lib/high-availability.jar"
   do
     echo "rm -f /var/gerrit/$jar"
     rm -f /var/gerrit/"$jar"
diff --git a/gerrit/etc/gerrit.config.template b/gerrit/etc/gerrit.config.template
index 0cccdc9..7488c31 100644
--- a/gerrit/etc/gerrit.config.template
+++ b/gerrit/etc/gerrit.config.template
@@ -8,6 +8,9 @@
 	installDbModule = com.googlesource.gerrit.plugins.multisite.GitModule
 	installModule = com.googlesource.gerrit.plugins.multisite.Module
 	installModule = com.gerritforge.gerrit.eventbroker.BrokerApiModule
+{% elif REFS_DB_ENABLED is defined and REFS_DB_ENABLED == "true" %}
+    installDbModule = com.ericsson.gerrit.plugins.highavailability.ValidationModule
+    installModule = com.gerritforge.gerrit.globalrefdb.validation.LibModule
 {% endif %}
 [core]
 	packedGitLimit = {{ JGIT_CACHE_SIZE }}
@@ -104,3 +107,9 @@
     maxRequestSize = 10485760
     securityProtocol = SSL
 {% endif %}
+
+{% if (MULTISITE_ENABLED is defined and MULTISITE_ENABLED == "true") or (REFS_DB_ENABLED is defined and REFS_DB_ENABLED == "true") %}
+[plugin "aws-dynamodb-refdb"]
+    locksTableName = {{ DYNAMODB_LOCKS_TABLE_NAME }}
+    refsDbTableName = {{ DYNAMODB_REFS_TABLE_NAME }}
+{% endif %}
\ No newline at end of file
diff --git a/gerrit/etc/high-availability.config.template b/gerrit/etc/high-availability.config.template
index db00a79..8a3b635 100644
--- a/gerrit/etc/high-availability.config.template
+++ b/gerrit/etc/high-availability.config.template
@@ -14,5 +14,7 @@
 {% if MULTISITE_ENABLED is defined and MULTISITE_ENABLED == "true" %}
 [websession]
   synchronize = false
-{% endif %}
-
+{% elif REFS_DB_ENABLED is defined and REFS_DB_ENABLED == "true" %}
+[ref-database]
+  enabled = true
+{% endif %}
\ No newline at end of file
diff --git a/gerrit/etc/zookeeper-refdb.config.template b/gerrit/etc/zookeeper-refdb.config.template
deleted file mode 100644
index 7e0b649..0000000
--- a/gerrit/etc/zookeeper-refdb.config.template
+++ /dev/null
@@ -1,4 +0,0 @@
-[ref-database "zookeeper"]
-  connectString = {{ MULTISITE_ZOOKEEPER_CONNECT_STRING }}
-  sslConnection = true
-  rootNode = {{ MULTISITE_ZOOKEEPER_ROOT_NODE }}
\ No newline at end of file
diff --git a/gerrit/setup_gerrit.py b/gerrit/setup_gerrit.py
index 5af5795..74ecdba 100755
--- a/gerrit/setup_gerrit.py
+++ b/gerrit/setup_gerrit.py
@@ -169,7 +169,10 @@
         'METRICS_CLOUDWATCH_DRY_RUN': os.getenv('METRICS_CLOUDWATCH_DRY_RUN'),
         'METRICS_CLOUDWATCH_EXCLUDE_METRICS_LIST': os.getenv('METRICS_CLOUDWATCH_EXCLUDE_METRICS_LIST'),
         'MULTISITE_ENABLED': os.getenv('MULTISITE_ENABLED'),
-        'MULTISITE_KAFKA_BROKERS': os.getenv('MULTISITE_KAFKA_BROKERS')
+        'MULTISITE_KAFKA_BROKERS': os.getenv('MULTISITE_KAFKA_BROKERS'),
+        'REFS_DB_ENABLED': os.getenv('REFS_DB_ENABLED'),
+        'DYNAMODB_LOCKS_TABLE_NAME': os.getenv('DYNAMODB_LOCKS_TABLE_NAME'),
+        'DYNAMODB_REFS_TABLE_NAME': os.getenv('DYNAMODB_REFS_TABLE_NAME'),
     })
     f.write(template.render(config_for_template))
 
@@ -214,22 +217,11 @@
         f.write(template.render(
             HA_PEER_URL=os.getenv('HA_PEER_URL'),
             HA_AUTOREINDEX_POLL_INTERVAL=os.getenv('HA_AUTOREINDEX_POLL_INTERVAL'),
-            MULTISITE_ENABLED=os.getenv('MULTISITE_ENABLED')
+            MULTISITE_ENABLED=os.getenv('MULTISITE_ENABLED'),
+            REFS_DB_ENABLED=os.getenv('REFS_DB_ENABLED')
         ))
 
 if setupMultiSite:
-    CONFIGURATION_FILE = "zookeeper-refdb.config"
-    CONFIGURATION_TARGET = GERRIT_CONFIG_DIRECTORY + CONFIGURATION_FILE
-    TEMPLATE_FILE = CONFIGURATION_FILE + ".template"
-
-    print("*** "+ CONFIGURATION_TARGET)
-    template = env.get_template("zookeeper-refdb.config.template")
-    with open(CONFIGURATION_TARGET, 'w', encoding='utf-8') as f:
-        f.write(template.render(
-            MULTISITE_ZOOKEEPER_CONNECT_STRING=os.getenv('MULTISITE_ZOOKEEPER_CONNECT_STRING'),
-            MULTISITE_ZOOKEEPER_ROOT_NODE=os.getenv('MULTISITE_ZOOKEEPER_ROOT_NODE')
-        ))
-
     CONFIGURATION_TARGET = GERRIT_CONFIG_DIRECTORY + "multi-site.config"
 
     print("*** "+ CONFIGURATION_TARGET)