Merge pull request #180 from Mirantis/cc

Contrail client cluster
diff --git a/ceilometer/server/cluster.yml b/ceilometer/server/cluster.yml
index 005379d..2b2030c 100644
--- a/ceilometer/server/cluster.yml
+++ b/ceilometer/server/cluster.yml
@@ -8,6 +8,7 @@
     server:
       enabled: true
       version: ${_param:ceilometer_version}
+      region: ${_param: openstack_region}
       cluster: true
       secret: ${_param:ceilometer_secret_key}
       ttl: 86400
diff --git a/designate/server/cluster.yml b/designate/server/cluster.yml
new file mode 100644
index 0000000..573ac66
--- /dev/null
+++ b/designate/server/cluster.yml
@@ -0,0 +1,59 @@
+classes:
+- service.designate.server.cluster
+- service.keepalived.cluster.single
+- system.haproxy.proxy.listen.openstack.designate
+- service.haproxy.proxy.single
+parameters:
+  designate:
+    _support:
+      sensu:
+        enabled: false
+    server:
+      enabled: true
+      local_bind: true
+      region: ${_param:openstack_region}
+      domain_id: ${_param:designate_domain_id}
+      version: ${_param:designate_version}
+      database:
+        engine: mysql
+        host: ${_param:openstack_database_address}
+        port: 3306
+        name:
+          main_database: designate
+          pool_manager: designate_pool_manager
+        user: designate
+        password: ${_param:mysql_designate_password}
+      identity:
+        engine: keystone
+        host: ${_param:openstack_control_address}
+        port: 35357
+        tenant: service
+        user: designate
+        password: ${_param:keystone_designate_password}
+      bind:
+        api:
+          address: ${_param:single_address}
+      message_queue:
+        engine: rabbitmq
+        port: 5672
+        members:
+        - host: ${_param:openstack_message_queue_node01_address}
+        - host: ${_param:openstack_message_queue_node02_address}
+        - host: ${_param:openstack_message_queue_node03_address}
+        user: openstack
+        password: ${_param:rabbitmq_openstack_password}
+        virtual_host: '/openstack'
+      pool:
+        pool_id: ${_param:designate_pool_id}
+        nameservers:
+          - uuid: ${_param:designate_node1_uuid}
+            host: ${_param:cluster_node01_address}
+            port: 53
+          - uuid: ${_param:designate_node2_uuid}
+            host: ${_param:cluster_node02_address}
+            port: 53
+        targets:
+          uuid: ${_param:designate_target_uuid}
+          options: 'port: 53, host: 127.0.0.1'
+          masters: 127.0.0.1:5354
+          type:  ${_param:designate_target_type}
diff --git a/designate/server/single.yml b/designate/server/single.yml
new file mode 100644
index 0000000..8805d53
--- /dev/null
+++ b/designate/server/single.yml
@@ -0,0 +1,37 @@
+classes:
+- service.designate.server.single
+- service.haproxy.proxy.single
+parameters:
+  designate:
+    server:
+      enabled: true
+      local_bind: true
+      region: ${_param:openstack_region}
+      domain_id: ${_param:designate_domain_id}
+      version: ${_param:designate_version}
+      bind:
+        api:
+          address: ${_param:single_address}
+      database:
+        engine: mysql
+        host: ${_param:openstack_database_address}
+        port: 3306
+        name:
+          main_database: designate
+          pool_manager: designate_pool_manager
+        user: designate
+        password: ${_param:mysql_designate_password}
+      identity:
+        engine: keystone
+        host: ${_param:openstack_control_address}
+        port: 35357
+        tenant: service
+        user: designate
+        password: ${_param:keystone_designate_password}
+      message_queue:
+        engine: rabbitmq
+        host: ${_param:cluster_vip_address}
+        port: 5672
+        user: openstack
+        password: ${_param:rabbitmq_openstack_password}
+        virtual_host: '/openstack'
\ No newline at end of file
diff --git a/grafana/server/plugin/piechart.yml b/grafana/server/plugin/piechart.yml
new file mode 100644
index 0000000..090872c
--- /dev/null
+++ b/grafana/server/plugin/piechart.yml
@@ -0,0 +1,6 @@
+parameters:
+  grafana:
+    server:
+      plugins:
+        grafana-piechart-panel:
+          enabled: true
diff --git a/haproxy/proxy/listen/cicd/aptly.yml b/haproxy/proxy/listen/cicd/aptly.yml
index 64115ff..fb24c1f 100644
--- a/haproxy/proxy/listen/cicd/aptly.yml
+++ b/haproxy/proxy/listen/cicd/aptly.yml
@@ -1,6 +1,8 @@
 parameters:
   _param:
+    haproxy_aptly_api_bind_host: ${_param:haproxy_bind_address}
     haproxy_aptly_api_bind_port: 8084
+    haproxy_aptly_public_bind_host: ${_param:haproxy_bind_address}
     haproxy_aptly_public_bind_port: 8085
   haproxy:
     proxy:
@@ -13,7 +15,7 @@
             - httplog
           balance: source
           binds:
-            - address: ${_param:haproxy_bind_address}
+            - address: ${_param:haproxy_aptly_api_bind_host}
               port: ${_param:haproxy_aptly_api_bind_port}
           servers:
             - name: ${_param:cluster_node01_name}
@@ -36,7 +38,7 @@
             - httplog
           balance: source
           binds:
-            - address: ${_param:haproxy_bind_address}
+            - address: ${_param:haproxy_aptly_public_bind_host}
               port: ${_param:haproxy_aptly_public_bind_port}
           servers:
             - name: ${_param:cluster_node01_name}
diff --git a/haproxy/proxy/listen/cicd/gerrit.yml b/haproxy/proxy/listen/cicd/gerrit.yml
index a9f0a3c..51d494b 100644
--- a/haproxy/proxy/listen/cicd/gerrit.yml
+++ b/haproxy/proxy/listen/cicd/gerrit.yml
@@ -1,7 +1,11 @@
 parameters:
   _param:
+    haproxy_gerrit_bind_host: ${_param:haproxy_bind_address}
     haproxy_gerrit_bind_port: 8080
+    haproxy_gerrit_ssh_bind_host: ${_param:haproxy_gerrit_bind_host}
     haproxy_gerrit_ssh_bind_port: 29418
+    haproxy_gerrit_ssl:
+      enabled: false
   haproxy:
     proxy:
       listen:
@@ -13,9 +17,13 @@
             - httpclose
             - httplog
           balance: source
+          http_request:
+            - action: "add-header X-Forwarded-Proto https"
+              condition: "if { ssl_fc }"
           binds:
-            - address: ${_param:haproxy_bind_address}
+            - address: ${_param:haproxy_gerrit_bind_host}
               port: ${_param:haproxy_gerrit_bind_port}
+              ssl: ${_param:haproxy_gerrit_ssl}
           servers:
             - name: ${_param:cluster_node01_name}
               host: ${_param:cluster_node01_address}
@@ -33,7 +41,7 @@
           mode: tcp
           balance: source
           binds:
-            - address: ${_param:haproxy_bind_address}
+            - address: ${_param:haproxy_gerrit_ssh_bind_host}
               port: ${_param:haproxy_gerrit_ssh_bind_port}
           servers:
             - name: ${_param:cluster_node01_name}
diff --git a/haproxy/proxy/listen/cicd/jenkins.yml b/haproxy/proxy/listen/cicd/jenkins.yml
index e91d9f2..eda12f8 100644
--- a/haproxy/proxy/listen/cicd/jenkins.yml
+++ b/haproxy/proxy/listen/cicd/jenkins.yml
@@ -1,7 +1,11 @@
 parameters:
   _param:
+    haproxy_jenkins_bind_host: ${_param:haproxy_bind_address}
     haproxy_jenkins_bind_port: 8081
+    haproxy_jenkins_jnlp_bind_host: ${_param:haproxy_jenkins_bind_host}
     haproxy_jenkins_jnlp_bind_port: 50000
+    haproxy_jenkins_ssl:
+      enabled: false
   haproxy:
     proxy:
       listen:
@@ -13,11 +17,15 @@
             - httpclose
             - httplog
           balance: source
+          http_request:
+            - action: "add-header X-Forwarded-Proto https"
+              condition: "if { ssl_fc }"
           http_response:
             - action: "del-header X-Frame-Options"
           binds:
-            - address: ${_param:haproxy_bind_address}
+            - address: ${_param:haproxy_jenkins_bind_host}
               port: ${_param:haproxy_jenkins_bind_port}
+              ssl: ${_param:haproxy_jenkins_ssl}
           servers:
             - name: ${_param:cluster_node01_name}
               host: ${_param:cluster_node01_address}
@@ -35,7 +43,7 @@
           mode: tcp
           balance: source
           binds:
-            - address: ${_param:haproxy_bind_address}
+            - address: ${_param:haproxy_jenkins_jnlp_bind_host}
               port: ${_param:haproxy_jenkins_jnlp_bind_port}
           servers:
             - name: ${_param:cluster_node01_name}
diff --git a/haproxy/proxy/listen/docker/registry.yml b/haproxy/proxy/listen/docker/registry.yml
index 2a86aa4..8d45e97 100644
--- a/haproxy/proxy/listen/docker/registry.yml
+++ b/haproxy/proxy/listen/docker/registry.yml
@@ -1,6 +1,9 @@
 parameters:
   _param:
+    haproxy_docker_registry_listen_host: ${_param:haproxy_bind_address}
     haproxy_docker_registry_listen_port: 5000
+    haproxy_docker_registry_ssl:
+      enabled: false
   haproxy:
     proxy:
       listen:
@@ -15,9 +18,9 @@
             - action: "add-header X-Forwarded-Proto https"
               condition: "if { ssl_fc }"
           binds:
-            - address: ${_param:haproxy_bind_address}
+            - address: ${_param:haproxy_docker_registry_listen_host}
               port: ${_param:haproxy_docker_registry_listen_port}
-              ssl: ${_param:cluster_ssl_certificate}
+              ssl: ${_param:haproxy_docker_registry_ssl}
           servers:
             - name: ${_param:cluster_node01_name}
               host: ${_param:cluster_node01_address}
diff --git a/haproxy/proxy/listen/openstack/designate.yml b/haproxy/proxy/listen/openstack/designate.yml
new file mode 100644
index 0000000..7a54af2
--- /dev/null
+++ b/haproxy/proxy/listen/openstack/designate.yml
@@ -0,0 +1,19 @@
+parameters:
+  haproxy:
+    proxy:
+      listen:
+        designate_api:
+          type: openstack-service
+          service_name: designate
+          binds:
+          - address: ${_param:cluster_vip_address}
+            port: 9001
+          servers:
+          - name: ${_param:cluster_node01_hostname}
+            host: ${_param:cluster_node01_address}
+            port: 9001
+            params: check inter 10s fastinter 2s downinter 3s rise 3 fall 3
+          - name: ${_param:cluster_node02_hostname}
+            host: ${_param:cluster_node02_address}
+            port: 9001
+            params: check inter 10s fastinter 2s downinter 3s rise 3 fall 3
diff --git a/jenkins/client/credential/gerrit.yml b/jenkins/client/credential/gerrit.yml
index 3b7eb0c..b42f5af 100644
--- a/jenkins/client/credential/gerrit.yml
+++ b/jenkins/client/credential/gerrit.yml
@@ -1,7 +1,9 @@
 parameters:
+  _param:
+    gerrit_admin_user: admin
   jenkins:
     client:
       credential:
         gerrit:
-          username: admin
+          username: ${_param:gerrit_admin_user}
           key: ${_param:gerrit_admin_private_key}
diff --git a/jenkins/client/init.yml b/jenkins/client/init.yml
index 36da8b6..02589e0 100644
--- a/jenkins/client/init.yml
+++ b/jenkins/client/init.yml
@@ -2,11 +2,15 @@
   - service.jenkins.support
   - service.jenkins.client
 parameters:
+  _param:
+    jenkins_client_user: none
+    jenkins_client_password: none
+    jenkins_master_host: ${_param:control_vip_address}
+    jenkins_master_port: 8081
   jenkins:
     client:
       master:
-        host: ${_param:cluster_vip_address}
-        port: 8081
-        # When Jenkins auth is enabled
-        #user: admin
-        #password: dummy
+        host: ${_param:jenkins_master_host}
+        port: ${_param:jenkins_master_port}
+        user: ${_param:jenkins_client_user}
+        password: ${_param:jenkins_client_password}
diff --git a/jenkins/master/config.yml b/jenkins/master/config.yml
index eb7e112..3c9268b 100644
--- a/jenkins/master/config.yml
+++ b/jenkins/master/config.yml
@@ -40,6 +40,9 @@
                   - method java.net.URLConnection setRequestProperty java.lang.String java.lang.String
                   - method java.util.LinkedHashMap$LinkedHashIterator hasNext
                   - method java.util.Map size
+                  - method java.util.regex.MatchResult group int
+                  - method java.util.regex.Matcher matches
+                  - method java.util.regex.Pattern matcher java.lang.CharSequence
                   - method org.jenkinsci.plugins.workflow.job.WorkflowRun doStop
                   - method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper build
                   - new groovy.json.JsonBuilder java.lang.Object
@@ -69,3 +72,18 @@
                   - staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods plus java.util.List java.util.Collection
                   - staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods putAt java.lang.Object java.lang.String java.lang.Object
                   - staticMethod org.codehaus.groovy.runtime.EncodingGroovyMethods encodeBase64 byte[]
+                  - staticMethod org.codehaus.groovy.runtime.ScriptBytecodeAdapter bitwiseNegate java.lang.Object
+                  - staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods println java.lang.Object java.lang.Object
+                  - method hudson.PluginWrapper getShortName
+                  - method hudson.PluginManager getPlugins
+                  - method jenkins.model.Jenkins getPluginManager
+                  - method hudson.model.ItemGroup getItem java.lang.String
+                  - method hudson.model.Job getLastBuild
+                  - method hudson.model.Run getResult
+                  - method hudson.model.Job getBuilds
+                  - staticMethod java.lang.String format java.lang.String java.lang.Object[]
+                  - staticMethod java.util.regex.Pattern quote java.lang.String
+                  - staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods findAll java.util.List groovy.lang.Closure
+                  - method java.util.Collection remove java.lang.Object
+                  - staticMethod java.lang.System exit int
+
diff --git a/jenkins/slave.yml b/jenkins/slave.yml
deleted file mode 100644
index 42f3ca0..0000000
--- a/jenkins/slave.yml
+++ /dev/null
@@ -1,35 +0,0 @@
-applications:
-  - jenkins
-classes:
-  - service.java.environment
-  - system.docker.host
-parameters:
-  _param:
-    java_environment_version: "8"
-    java_environment_platform: openjdk
-  java:
-    environment:
-      headless: true
-  jenkins:
-    slave:
-      enabled: true
-      pkgs: false
-      sudo: false
-      scripts: []
-      master:
-        host: ${_param:control_vip_address}
-        port: 8081
-        protocol: http
-#      user:
-#        name: admin
-#        password: ${_param:jenkins_admin_password}
-  linux:
-    system:
-      user:
-        jenkins:
-          enabled: true
-          name: jenkins
-          home: /var/lib/jenkins
-          sudo: false
-          groups:
-            - docker
diff --git a/jenkins/slave/docker.yml b/jenkins/slave/docker.yml
new file mode 100644
index 0000000..b134225
--- /dev/null
+++ b/jenkins/slave/docker.yml
@@ -0,0 +1,9 @@
+classes:
+  - system.jenkins.slave
+parameters:
+  linux:
+    system:
+      user:
+        jenkins:
+          groups:
+            - docker
diff --git a/jenkins/slave/init.yml b/jenkins/slave/init.yml
new file mode 100644
index 0000000..c445c14
--- /dev/null
+++ b/jenkins/slave/init.yml
@@ -0,0 +1,37 @@
+applications:
+  - jenkins
+classes:
+  - service.java.environment
+parameters:
+  _param:
+    java_environment_version: "8"
+    java_environment_platform: openjdk
+    jenkins_slave_user: none
+    jenkins_slave_password: none
+    jenkins_master_host: ${_param:control_vip_address}
+    jenkins_master_port: 8081
+    jenkins_master_protocol: http
+  java:
+    environment:
+      headless: true
+  jenkins:
+    slave:
+      enabled: true
+      pkgs: false
+      sudo: false
+      scripts: []
+      master:
+        host: ${_param:jenkins_master_host}
+        port: ${_param:jenkins_master_port}
+        protocol: ${_param:jenkins_master_protocol}
+      user:
+        name: ${_param:jenkins_slave_user}
+        password: ${_param:jenkins_slave_password}
+  linux:
+    system:
+      user:
+        jenkins:
+          enabled: true
+          name: jenkins
+          home: /var/lib/jenkins
+          sudo: false
diff --git a/jenkins/slave/libvirt.yml b/jenkins/slave/libvirt.yml
new file mode 100644
index 0000000..e40b841
--- /dev/null
+++ b/jenkins/slave/libvirt.yml
@@ -0,0 +1,25 @@
+classes:
+  - system.jenkins.slave
+  - service.iptables.server
+parameters:
+  linux:
+    system:
+      user:
+        jenkins:
+          groups:
+            - kvm
+            - libvirtd
+      package:
+        qemu:
+          version: latest
+        libvirt-bin:
+          version: latest
+  # Ensure FORWARD chain to be ACCEPT to avoid issue when running with docker
+  # 1.13 and newer that sets chain to DROP, see:
+  #   https://github.com/docker/docker/pull/28257
+  iptables:
+    service:
+      enabled: true
+      chain:
+        FORWARD:
+          policy: ACCEPT
diff --git a/keystone/client/service/designate.yml b/keystone/client/service/designate.yml
index 4d95b2e..4018712 100644
--- a/keystone/client/service/designate.yml
+++ b/keystone/client/service/designate.yml
@@ -12,19 +12,19 @@
                   is_admin: true
                   password: ${_param:keystone_designate_password}
                   email: ${_param:admin_email}
-    service:
-      designate:
-          type: dns
-          description: OpenStack DNS service
-          endpoints:
-            - region: ${_param:openstack_region}
-              public_address: ${_param:cluster_public_host}
-              public_protocol: ${_param:cluster_public_protocol}
-              public_port: 9001
-              public_path: '/'
-              internal_address: ${_param:designate_service_host}
-              internal_port: 9001
-              internal_path: '/'
-              admin_address: ${_param:designate_service_host}
-              admin_port: 9001
-              admin_path: '/'
+          service:
+            designate:
+                type: dns
+                description: OpenStack DNS service
+                endpoints:
+                  - region: ${_param:openstack_region}
+                    public_address: ${_param:cluster_public_host}
+                    public_protocol: ${_param:cluster_public_protocol}
+                    public_port: 9001
+                    public_path: '/'
+                    internal_address: ${_param:designate_service_host}
+                    internal_port: 9001
+                    internal_path: '/'
+                    admin_address: ${_param:designate_service_host}
+                    admin_port: 9001
+                    admin_path: '/'
diff --git a/linux/system/haveged.yml b/linux/system/haveged.yml
new file mode 100644
index 0000000..5c0be15
--- /dev/null
+++ b/linux/system/haveged.yml
@@ -0,0 +1,5 @@
+parameters:
+  linux:
+    system:
+      haveged:
+        enabled: true
diff --git a/linux/system/motd/dynamic.yml b/linux/system/motd/dynamic.yml
new file mode 100644
index 0000000..9589e8e
--- /dev/null
+++ b/linux/system/motd/dynamic.yml
@@ -0,0 +1,19 @@
+parameters:
+  linux:
+    system:
+      motd:
+        - warning: |
+            #!/bin/sh
+            printf "WARNING: This is private network.\n"
+            printf "  Unauthorized access is strictly prohibited.\n"
+            printf "\n"
+        - info: |
+            #!/bin/sh
+            printf -- "------------------------------------------------------\n"
+            printf " Hostname     |  $(hostname)\n"
+            printf " Domain       |  $(hostname -d)\n"
+            printf " System       |  %s\n" "$(lsb_release -s -d)"
+            printf " Kernel       |  %s\n" "$(uname -r)"
+            printf " Uptime       |  %s\n" "$(uptime -p)"
+            printf " Load Average |  %s\n" "$(cat /proc/loadavg | awk '{print $1", "$2", "$3}')"
+            printf -- "------------------------------------------------------\n"
diff --git a/linux/system/motd/static.yml b/linux/system/motd/static.yml
new file mode 100644
index 0000000..774abc6
--- /dev/null
+++ b/linux/system/motd/static.yml
@@ -0,0 +1,12 @@
+parameters:
+  linux:
+    system:
+      motd: |
+        WARNING: This is private network
+        Unauthorized access is strictly prohibited
+
+        ------------------------------------------------------
+         Hostname     |  ${linux:system:name}
+         Domain       |  ${linux:system:domain}
+        ------------------------------------------------------
+        
diff --git a/linux/system/prompt/init.yml b/linux/system/prompt/init.yml
new file mode 100644
index 0000000..2f0120d
--- /dev/null
+++ b/linux/system/prompt/init.yml
@@ -0,0 +1,7 @@
+parameters:
+  linux:
+    system:
+      prompt:
+        default: \\n\\[\\033[0;37m\\]\\D{%y/%m/%d %H:%M:%S} ${linux:system:name}.${linux:system:domain}\\[\\e[0m\\]\\n\\[\\e[1;39m\\][\\u@\\h:\\w]\\[\\e[0m\\]
+      bash:
+        preserve_history: true
diff --git a/linux/system/prompt/production.yml b/linux/system/prompt/production.yml
new file mode 100644
index 0000000..f878460
--- /dev/null
+++ b/linux/system/prompt/production.yml
@@ -0,0 +1,7 @@
+classes:
+  - system.linux.system.prompt
+parameters:
+  linux:
+    system:
+      prompt:
+        default: \\n\\[\\033[0;37m\\]\\D{%y/%m/%d %H:%M:%S} ${linux:system:name}.${linux:system:domain}\\[\\e[0m\\]\\n\\[\\e[1;31m\\][\\u@\\h:\\w]\\[\\e[0m\\]
diff --git a/mysql/client/database/designate.yml b/mysql/client/database/designate.yml
new file mode 100644
index 0000000..cee6ff1
--- /dev/null
+++ b/mysql/client/database/designate.yml
@@ -0,0 +1,17 @@
+parameters:
+  mysql:
+    client:
+      server:
+        database:
+          database:
+            designate:
+              encoding: utf8
+              users:
+              - name: designate
+                password: ${_param:mysql_designate_password}
+                host: '%'
+                rights: all
+              - name: designate
+                password: ${_param:mysql_designate_password}
+                host: ${_param:single_address}
+                rights: all
\ No newline at end of file
diff --git a/mysql/client/database/designate_pool_manager.yml b/mysql/client/database/designate_pool_manager.yml
new file mode 100644
index 0000000..6913bd4
--- /dev/null
+++ b/mysql/client/database/designate_pool_manager.yml
@@ -0,0 +1,17 @@
+parameters:
+  mysql:
+    client:
+      server:
+        database:
+          database:
+            designate_pool_manager:
+              encoding: utf8
+              users:
+              - name: designate
+                password: ${_param:mysql_designate_password}
+                host: '%'
+                rights: all
+              - name: designate
+                password: ${_param:mysql_designate_password}
+                host: ${_param:single_address}
+                rights: all
diff --git a/nginx/server/proxy/openstack/designate.yml b/nginx/server/proxy/openstack/designate.yml
new file mode 100644
index 0000000..2b8ffce
--- /dev/null
+++ b/nginx/server/proxy/openstack/designate.yml
@@ -0,0 +1,19 @@
+  parameters:
+  _param:
+    nginx_proxy_openstack_api_host: ${_param:cluster_public_host}
+  nginx:
+    server:
+      enabled: true
+      site:
+        nginx_proxy_openstack_api_designate:
+          enabled: true
+          type: nginx_proxy
+          name: openstack_api_designate
+          proxy:
+            host: ${_param:nginx_proxy_openstack_api_proxy_host}
+            port: 9001
+            protocol: http
+          host:
+            name: ${_param:nginx_proxy_openstack_api_host}
+            port: 9001
+          ssl: ${_param:nginx_proxy_ssl}
diff --git a/reclass/storage/system/openstack_dns_cluster.yml b/reclass/storage/system/openstack_dns_cluster.yml
new file mode 100644
index 0000000..d134c88
--- /dev/null
+++ b/reclass/storage/system/openstack_dns_cluster.yml
@@ -0,0 +1,27 @@
+parameters:
+  _param:
+    openstack_dns_node01_hostname: dns01
+    openstack_dns_node02_hostname: dns02
+  reclass:
+    storage:
+      node:
+        openstack_dns_node01:
+          name: ${_param:openstack_dns_node01_hostname}
+          domain: ${_param:cluster_domain}
+          classes:
+          - cluster.${_param:cluster_name}.openstack.dns
+          params:
+            salt_master_host: ${_param:reclass_config_master}
+            linux_system_codename: trusty
+            single_address: ${_param:openstack_dns_node01_address}
+            keepalived_vip_priority: 110
+        openstack_dns_node02:
+          name: ${_param:openstack_dns_node02_hostname}
+          domain: ${_param:cluster_domain}
+          classes:
+          - cluster.${_param:cluster_name}.openstack.dns
+          params:
+            salt_master_host: ${_param:reclass_config_master}
+            linux_system_codename: trusty
+            single_address: ${_param:openstack_dns_node02_address}
+            keepalived_vip_priority: 111
diff --git a/salt/control/cluster/openstack_dns_cluster.yml b/salt/control/cluster/openstack_dns_cluster.yml
new file mode 100644
index 0000000..4ca0e00
--- /dev/null
+++ b/salt/control/cluster/openstack_dns_cluster.yml
@@ -0,0 +1,22 @@
+parameters:
+  salt:
+    control:
+      size:
+        openstack.dns:
+          cpu: 2
+          ram: 4096
+          disk_profile: small
+          net_profile: default
+      cluster:
+        internal:
+          domain: ${_param:cluster_domain}
+          engine: virt
+          node:
+            dns01:
+              provider: kvm01.${_param:cluster_domain}
+              image: ${_param:salt_control_xenial_image}
+              size: openstack.dns
+            dns02:
+              provider: kvm02.${_param:cluster_domain}
+              image: ${_param:salt_control_xenial_image}
+              size: openstack.dns
diff --git a/salt/master/formula/git/openstack.yml b/salt/master/formula/git/openstack.yml
index 6f296c4..86e23b2 100644
--- a/salt/master/formula/git/openstack.yml
+++ b/salt/master/formula/git/openstack.yml
@@ -28,6 +28,10 @@
               source: git
               address: '${_param:salt_master_environment_repository}/salt-formula-cinder.git'
               revision: ${_param:salt_master_environment_revision}
+            designate:
+              source: git
+              address: '${_param:salt_master_environment_repository}/salt-formula-designate.git'
+              revision: ${_param:salt_master_environment_revision}
             galera:
               source: git
               address: '${_param:salt_master_environment_repository}/salt-formula-galera.git'
diff --git a/salt/master/formula/pkg/openstack.yml b/salt/master/formula/pkg/openstack.yml
index b795e06..1269bd1 100644
--- a/salt/master/formula/pkg/openstack.yml
+++ b/salt/master/formula/pkg/openstack.yml
@@ -31,6 +31,9 @@
             glusterfs:
               source: pkg
               name: salt-formula-glusterfs
+            designate:
+              source: pkg
+              name: salt-formula-designate
             haproxy:
               source: pkg
               name: salt-formula-haproxy