diff --git a/ansible/roles/aodh/defaults/main.yml b/ansible/roles/aodh/defaults/main.yml
index 0f8a29d718e254294ff7c30dda34a680c2246cce..19f56f09eb0dba787a31def5245972701d9f9402 100644
--- a/ansible/roles/aodh/defaults/main.yml
+++ b/ansible/roles/aodh/defaults/main.yml
@@ -55,6 +55,12 @@ aodh_services:
 # change this option.
 aodh_evaluation_interval: 300
 
+####################
+# Config Validate
+####################
+aodh_config_validation:
+  - generator: "/aodh/aodh/cmd/aodh-config-generator.conf"
+    config: "/etc/aodh/aodh.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/aodh/tasks/config_validate.yml b/ansible/roles/aodh/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..887b3cf0e5d599a1e3df810874b3de917c94f15d
--- /dev/null
+++ b/ansible/roles/aodh/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ aodh_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ aodh_config_validation }}"
diff --git a/ansible/roles/barbican/defaults/main.yml b/ansible/roles/barbican/defaults/main.yml
index 0f7778175a87a6e1030d57c4273ce727fde28efa..f8629a5a63ef83dd9fa29e6c96700cc9b871d589 100644
--- a/ansible/roles/barbican/defaults/main.yml
+++ b/ansible/roles/barbican/defaults/main.yml
@@ -40,6 +40,12 @@ barbican_services:
     dimensions: "{{ barbican_worker_dimensions }}"
     healthcheck: "{{ barbican_worker_healthcheck }}"
 
+####################
+# Config Validate
+####################
+barbican_config_validation:
+  - generator: "/barbican/etc/oslo-config-generator/barbican.conf"
+    config: "/etc/barbican/barbican.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/barbican/tasks/config_validate.yml b/ansible/roles/barbican/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..31143931f7993121653a849e2547fec3e927a714
--- /dev/null
+++ b/ansible/roles/barbican/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ barbican_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ barbican_config_validation }}"
diff --git a/ansible/roles/bifrost/tasks/config_validate.yml b/ansible/roles/bifrost/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/bifrost/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/blazar/defaults/main.yml b/ansible/roles/blazar/defaults/main.yml
index 36d9d24a132f21846435ddfc482eef5df6f7afec..bdcf00bc5e2a3a0841bc57394dc22db78d9dd391 100644
--- a/ansible/roles/blazar/defaults/main.yml
+++ b/ansible/roles/blazar/defaults/main.yml
@@ -34,6 +34,13 @@ blazar_services:
 ####################
 blazar_aggregate_pool_name: "freepool"
 
+####################
+# Config Validate
+####################
+blazar_config_validation:
+  - generator: "/blazar/etc/blazar/blazar-config-generator.conf"
+    config: "/etc/blazar/blazar.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/blazar/tasks/config_validate.yml b/ansible/roles/blazar/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9a18ef3d5f3090b0315a2aa0bac8903b2ce155c2
--- /dev/null
+++ b/ansible/roles/blazar/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ blazar_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ blazar_config_validation }}"
diff --git a/ansible/roles/ceilometer/defaults/main.yml b/ansible/roles/ceilometer/defaults/main.yml
index 7cbcd5674ae3c0be6acc76c4d6b7798c971453ff..d9024926eb519d16f0669f27e07f8b57df742bf1 100644
--- a/ansible/roles/ceilometer/defaults/main.yml
+++ b/ansible/roles/ceilometer/defaults/main.yml
@@ -34,6 +34,12 @@ ceilometer_services:
     dimensions: "{{ ceilometer_ipmi_dimensions }}"
     healthcheck: "{{ ceilometer_ipmi_healthcheck }}"
 
+####################
+# Config Validate
+####################
+ceilometer_config_validation:
+  - generator: "/ceilometer/etc/ceilometer/ceilometer-config-generator.conf"
+    config: "/etc/ceilometer/ceilometer.conf"
 
 ####################
 # Docker
diff --git a/ansible/roles/ceilometer/tasks/config_validate.yml b/ansible/roles/ceilometer/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ef646be6b31215199cccee91c018561f60854aaa
--- /dev/null
+++ b/ansible/roles/ceilometer/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ ceilometer_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ ceilometer_config_validation }}"
diff --git a/ansible/roles/ceph-rgw/tasks/config_validate.yml b/ansible/roles/ceph-rgw/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/ceph-rgw/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/cinder/defaults/main.yml b/ansible/roles/cinder/defaults/main.yml
index ab764edccd2a84a09d3dc0a4395fe7ec33f0adbf..f33e517d0700401c5841b801653a39eb9ec47eef 100644
--- a/ansible/roles/cinder/defaults/main.yml
+++ b/ansible/roles/cinder/defaults/main.yml
@@ -52,6 +52,13 @@ cinder_services:
     dimensions: "{{ cinder_backup_dimensions }}"
     healthcheck: "{{ cinder_backup_healthcheck }}"
 
+####################
+# Config Validate
+####################
+cinder_config_validation:
+  - generator: "/cinder/tools/config/cinder-config-generator.conf"
+    config: "/etc/cinder/cinder.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/cinder/tasks/config_validate.yml b/ansible/roles/cinder/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1c9b602455a15d2aec7bf1a58e495238341c1e38
--- /dev/null
+++ b/ansible/roles/cinder/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ cinder_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ cinder_config_validation }}"
diff --git a/ansible/roles/cloudkitty/defaults/main.yml b/ansible/roles/cloudkitty/defaults/main.yml
index dedf4161fa099f059841565b1d04630073a1bcee..e10872655049f56b36a8bc03dabd481b5f01efbf 100644
--- a/ansible/roles/cloudkitty/defaults/main.yml
+++ b/ansible/roles/cloudkitty/defaults/main.yml
@@ -28,6 +28,12 @@ cloudkitty_services:
     dimensions: "{{ cloudkitty_processor_dimensions }}"
     healthcheck: "{{ cloudkitty_processor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+cloudkitty_config_validation:
+  - generator: "/cloudkitty/etc/oslo-config-generator/cloudkitty.conf"
+    config: "/etc/cloudkitty/cloudkitty.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/cloudkitty/tasks/config_validate.yml b/ansible/roles/cloudkitty/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4806fd83a7acd3e5603ee4acaafe5dd2f06556e6
--- /dev/null
+++ b/ansible/roles/cloudkitty/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ cloudkitty_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ cloudkitty_config_validation }}"
diff --git a/ansible/roles/collectd/tasks/config_validate.yml b/ansible/roles/collectd/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/collectd/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/common/tasks/config_validate.yml b/ansible/roles/common/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/common/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/cyborg/defaults/main.yml b/ansible/roles/cyborg/defaults/main.yml
index eb92290b8390f57c66c5b3b1a33ced6e5529568f..69ca507f64499d976d2cd7f23d291d29e467a5a0 100644
--- a/ansible/roles/cyborg/defaults/main.yml
+++ b/ansible/roles/cyborg/defaults/main.yml
@@ -26,6 +26,13 @@ cyborg_services:
     dimensions: "{{ cyborg_conductor_dimensions }}"
     healthcheck: "{{ cyborg_conductor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+cyborg_config_validation:
+  - generator: "/cyborg/tools/config/cyborg-config-generator.conf"
+    config: "/etc/cyborg/cyborg.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/cyborg/tasks/config_validate.yml b/ansible/roles/cyborg/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fd9c0723607851038807a32212cbd31aea617558
--- /dev/null
+++ b/ansible/roles/cyborg/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ cyborg_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ cyborg_config_validation }}"
diff --git a/ansible/roles/designate/defaults/main.yml b/ansible/roles/designate/defaults/main.yml
index 9619a1689f6673b2d89a3f25e77add6738e30e60..926a358b44e57d51d23ac1dd76e0356e99358dc7 100644
--- a/ansible/roles/designate/defaults/main.yml
+++ b/ansible/roles/designate/defaults/main.yml
@@ -70,6 +70,12 @@ designate_services:
     dimensions: "{{ designate_sink_dimensions }}"
     healthcheck: "{{ designate_sink_healthcheck }}"
 
+####################
+# Config Validate
+####################
+designate_config_validation:
+  - generator: "/designate/etc/designate/designate-config-generator.conf"
+    config: "/etc/designate/designate.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/designate/tasks/config_validate.yml b/ansible/roles/designate/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..febfb66bf7062aaf40834c2614ae47797cbdec03
--- /dev/null
+++ b/ansible/roles/designate/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ designate_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ designate_config_validation }}"
diff --git a/ansible/roles/etcd/tasks/config_validate.yml b/ansible/roles/etcd/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/etcd/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/freezer/defaults/main.yml b/ansible/roles/freezer/defaults/main.yml
index 1956c1e26932fd41f28f3c930f6f78847f376c5e..716fdc4326feb01f0cfb4c892342e0bc4e3661a4 100644
--- a/ansible/roles/freezer/defaults/main.yml
+++ b/ansible/roles/freezer/defaults/main.yml
@@ -26,6 +26,13 @@ freezer_services:
     volumes: "{{ freezer_scheduler_default_volumes + freezer_scheduler_extra_volumes }}"
     dimensions: "{{ freezer_scheduler_dimensions }}"
 
+####################
+# Config Validate
+####################
+freezer_config_validation:
+  - generator: "/freezer/etc/config-generator.conf"
+    config: "/etc/freezer/freezer.conf"
+
 ####################
 ## Database
 #####################
diff --git a/ansible/roles/freezer/tasks/config_validate.yml b/ansible/roles/freezer/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c734493b309b5d91061e98ff1672e9d88af7e265
--- /dev/null
+++ b/ansible/roles/freezer/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ freezer_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ freezer_config_validation }}"
diff --git a/ansible/roles/glance/defaults/main.yml b/ansible/roles/glance/defaults/main.yml
index 5ca70d9c70ab81e3cd922704d98f86e81f0de67f..114cce55e51d34c70722a88d529032fc5c3d771a 100644
--- a/ansible/roles/glance/defaults/main.yml
+++ b/ansible/roles/glance/defaults/main.yml
@@ -65,6 +65,19 @@ glance_services:
         custom_member_list: "{{ haproxy_tls_members.split(';') }}"
         tls_backend: "yes"
 
+####################
+# Config Validate
+####################
+glance_config_validation:
+  - generator: "/glance/etc/oslo-config-generator/glance-api.conf"
+    config: "/etc/glance/glance-api.conf"
+  - generator: "/glance/etc/oslo-config-generator/glance-cache.conf"
+    config: "/etc/glance/glance-cache.conf"
+  - generator: "/glance/etc/oslo-config-generator/glance-manage.conf"
+    config: "/etc/glance/glance-manage.conf"
+  - generator: "/glance/etc/oslo-config-generator/glance-scrubber.conf"
+    config: "/etc/glance/glance-scrubber.conf"
+
 ####################
 # HAProxy
 ####################
diff --git a/ansible/roles/glance/tasks/config_validate.yml b/ansible/roles/glance/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f4f0a66381bc580da605d8b370388fcfb0e633f7
--- /dev/null
+++ b/ansible/roles/glance/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ glance_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ glance_config_validation }}"
diff --git a/ansible/roles/gnocchi/defaults/main.yml b/ansible/roles/gnocchi/defaults/main.yml
index e15582f50c1d82e3b0cdf5ec3b6492fe39e8fac8..dbb5ef5e34d36b77d364955567a6edd8ad7f85e1 100644
--- a/ansible/roles/gnocchi/defaults/main.yml
+++ b/ansible/roles/gnocchi/defaults/main.yml
@@ -36,6 +36,12 @@ gnocchi_services:
     dimensions: "{{ gnocchi_statsd_dimensions }}"
     healthcheck: "{{ gnocchi_statsd_healthcheck }}"
 
+####################
+# Config Validate
+####################
+gnocchi_config_validation:
+  - generator: "/gnocchi/gnocchi/gnocchi-config-generator.conf"
+    config: "/etc/gnocchi/gnocchi.conf"
 
 ####################
 # Swift
diff --git a/ansible/roles/gnocchi/tasks/config_validate.yml b/ansible/roles/gnocchi/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a8fa5f57ee8d787bdea4ee0ac1e05e6e180c0023
--- /dev/null
+++ b/ansible/roles/gnocchi/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ gnocchi_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ gnocchi_config_validation }}"
diff --git a/ansible/roles/grafana/tasks/config_validate.yml b/ansible/roles/grafana/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/grafana/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/hacluster/tasks/config_validate.yml b/ansible/roles/hacluster/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/hacluster/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/heat/defaults/main.yml b/ansible/roles/heat/defaults/main.yml
index 37a4622f62baaad248a086076f331f972107cdcd..d4b630df1c95e562be14dc6663136e23d9d2b3cf 100644
--- a/ansible/roles/heat/defaults/main.yml
+++ b/ansible/roles/heat/defaults/main.yml
@@ -55,6 +55,13 @@ heat_services:
     dimensions: "{{ heat_engine_dimensions }}"
     healthcheck: "{{ heat_engine_healthcheck }}"
 
+####################
+# Config Validate
+####################
+heat_config_validation:
+  - generator: "/heat/config-generator.conf"
+    config: "/etc/heat/heat.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/heat/tasks/config_validate.yml b/ansible/roles/heat/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e1931df598b04d62e706980d4cfe55fe1a88bc3e
--- /dev/null
+++ b/ansible/roles/heat/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ heat_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ heat_config_validation }}"
diff --git a/ansible/roles/horizon/tasks/config_validate.yml b/ansible/roles/horizon/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/horizon/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/influxdb/tasks/config_validate.yml b/ansible/roles/influxdb/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/influxdb/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/ironic/defaults/main.yml b/ansible/roles/ironic/defaults/main.yml
index ad735938bd29116bd9129ab2f573ee0167075241..7684cf97a06f7eca34981c42d5d16ba5d1487ebf 100644
--- a/ansible/roles/ironic/defaults/main.yml
+++ b/ansible/roles/ironic/defaults/main.yml
@@ -84,6 +84,12 @@ ironic_services:
     volumes: "{{ ironic_dnsmasq_default_volumes + ironic_dnsmasq_extra_volumes }}"
     dimensions: "{{ ironic_dnsmasq_dimensions }}"
 
+####################
+# Config Validate
+####################
+ironic_config_validation:
+  - generator: "/ironic/tools/config/ironic-config-generator.conf"
+    config: "/etc/ironic/ironic.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/ironic/tasks/config_validate.yml b/ansible/roles/ironic/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7b1806f3463177c2a8725e869b758af4d39a31d8
--- /dev/null
+++ b/ansible/roles/ironic/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ ironic_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ ironic_config_validation }}"
diff --git a/ansible/roles/iscsi/tasks/config_validate.yml b/ansible/roles/iscsi/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/iscsi/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/kafka/tasks/config_validate.yml b/ansible/roles/kafka/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/kafka/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/keystone/defaults/main.yml b/ansible/roles/keystone/defaults/main.yml
index d0710e308d54050f9a5f5a130cd6883c4a379c25..94de04d971873e60912e08ed511025565910922d 100644
--- a/ansible/roles/keystone/defaults/main.yml
+++ b/ansible/roles/keystone/defaults/main.yml
@@ -61,6 +61,13 @@ keystone_services:
     dimensions: "{{ keystone_fernet_dimensions }}"
     healthcheck: "{{ keystone_fernet_healthcheck }}"
 
+####################
+# Config Validate
+####################
+keystone_config_validation:
+  - generator: "/keystone/config-generator/keystone.conf"
+    config: "/etc/keystone/keystone.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/keystone/tasks/config_validate.yml b/ansible/roles/keystone/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..400463d208999b4036caa2ab468dde12cd1db659
--- /dev/null
+++ b/ansible/roles/keystone/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ keystone_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ keystone_config_validation }}"
diff --git a/ansible/roles/kuryr/defaults/main.yml b/ansible/roles/kuryr/defaults/main.yml
index 92c60fc5bd8a3c07ff6f029d8382c247a8c261c4..0a2cbfa6213b30a8ee44059cd91f6486c4dc27ec 100644
--- a/ansible/roles/kuryr/defaults/main.yml
+++ b/ansible/roles/kuryr/defaults/main.yml
@@ -20,6 +20,12 @@ kuryr_services:
     dimensions: "{{ kuryr_dimensions }}"
     healthcheck: "{{ kuryr_healthcheck }}"
 
+####################
+# Config Validate
+####################
+kuryr_config_validation:
+  - generator: "/kuryr/etc/kuryr-config-generator.conf"
+    config: "/etc/kuryr/kuryr.conf"
 
 ####################
 # Docker
diff --git a/ansible/roles/kuryr/tasks/config_validate.yml b/ansible/roles/kuryr/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9ed33e0f20dd9f79b75e74adc3b5eb493897c051
--- /dev/null
+++ b/ansible/roles/kuryr/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ kuryr_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ kuryr_config_validation }}"
diff --git a/ansible/roles/loadbalancer/tasks/config_validate.yml b/ansible/roles/loadbalancer/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/loadbalancer/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/magnum/defaults/main.yml b/ansible/roles/magnum/defaults/main.yml
index 1a051095d8789367daefce9619f3ad25c3d66a04..c929842e5b4cb35675a821b3ce8a6a967cee824c 100644
--- a/ansible/roles/magnum/defaults/main.yml
+++ b/ansible/roles/magnum/defaults/main.yml
@@ -31,6 +31,12 @@ magnum_services:
     dimensions: "{{ magnum_conductor_dimensions }}"
     healthcheck: "{{ magnum_conductor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+magnum_config_validation:
+  - generator: "/magnum/etc/magnum/magnum-config-generator.conf"
+    config: "/etc/magnum/magnum.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/magnum/tasks/config_validate.yml b/ansible/roles/magnum/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fae91de74e7b06320b9241f7b9c34335686959cd
--- /dev/null
+++ b/ansible/roles/magnum/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ magnum_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ magnum_config_validation }}"
diff --git a/ansible/roles/manila/defaults/main.yml b/ansible/roles/manila/defaults/main.yml
index 895290a329093a14caf8054407e4b20b405bc1ae..8f5a13f1da5581b03f996acfc52c69ae7d0c3ef9 100644
--- a/ansible/roles/manila/defaults/main.yml
+++ b/ansible/roles/manila/defaults/main.yml
@@ -46,6 +46,12 @@ manila_services:
     dimensions: "{{ manila_data_dimensions }}"
     healthcheck: "{{ manila_data_healthcheck }}"
 
+####################
+# Config Validate
+####################
+manila_config_validation:
+  - generator: "/manila/etc/oslo-config-generator/manila.conf"
+    config: "/etc/manila/manila.conf"
 
 #####################
 ## Database
diff --git a/ansible/roles/manila/tasks/config_validate.yml b/ansible/roles/manila/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6f14e38f6b59bf384018d39272fb6ae29e7d9c07
--- /dev/null
+++ b/ansible/roles/manila/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ manila_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ manila_config_validation }}"
diff --git a/ansible/roles/mariadb/tasks/config_validate.yml b/ansible/roles/mariadb/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/mariadb/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/masakari/defaults/main.yml b/ansible/roles/masakari/defaults/main.yml
index d9bc87a6fea5557fcee9aeb4c46aa5461aa71b31..e581e2ac4619d179a020d51625115380a244403e 100644
--- a/ansible/roles/masakari/defaults/main.yml
+++ b/ansible/roles/masakari/defaults/main.yml
@@ -42,6 +42,12 @@ masakari_services:
     volumes: "{{ masakari_hostmonitor_default_volumes + masakari_hostmonitor_extra_volumes }}"
     dimensions: "{{ masakari_hostmonitor_dimensions }}"
 
+####################
+# Config Validate
+####################
+masakari_config_validation:
+  - generator: "/masakari/etc/masakari/masakari-config-generator.conf"
+    config: "/etc/masakari/masakari.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/masakari/tasks/config_validate.yml b/ansible/roles/masakari/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..de3be4b384692b167231284860b1429b9180b031
--- /dev/null
+++ b/ansible/roles/masakari/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ masakari_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ masakari_config_validation }}"
diff --git a/ansible/roles/memcached/tasks/config_validate.yml b/ansible/roles/memcached/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/memcached/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/mistral/defaults/main.yml b/ansible/roles/mistral/defaults/main.yml
index b00acd8da38277edcd92cdb4a623dbb544754a32..3d1e2c64d1e007c1e6fea4c229b3037b4ee99fc5 100644
--- a/ansible/roles/mistral/defaults/main.yml
+++ b/ansible/roles/mistral/defaults/main.yml
@@ -44,6 +44,12 @@ mistral_services:
     dimensions: "{{ mistral_executor_dimensions }}"
     healthcheck: "{{ mistral_executor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+mistral_config_validation:
+  - generator: "/mistral/tools/config/config-generator.mistral.conf"
+    config: "/etc/mistral/mistral.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/mistral/tasks/config_validate.yml b/ansible/roles/mistral/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..91fad6d18f2eca73d2f7aa65ca7c0f3f1e3f5746
--- /dev/null
+++ b/ansible/roles/mistral/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ mistral_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ mistral_config_validation }}"
diff --git a/ansible/roles/multipathd/tasks/config_validate.yml b/ansible/roles/multipathd/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/multipathd/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/murano/defaults/main.yml b/ansible/roles/murano/defaults/main.yml
index e97ce75dbbfeb0dc67d8ead3b996d4f600b65bbb..473a3d189ef7310988c801cfe4ce47270e41be96 100644
--- a/ansible/roles/murano/defaults/main.yml
+++ b/ansible/roles/murano/defaults/main.yml
@@ -26,6 +26,12 @@ murano_services:
     volumes: "{{ murano_engine_default_volumes + murano_engine_extra_volumes }}"
     dimensions: "{{ murano_engine_dimensions }}"
 
+####################
+# Config Validate
+####################
+murano_config_validation:
+  - generator: "/murano/etc/oslo-config-generator/murano.conf"
+    config: "/etc/murano/murano.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/murano/tasks/config_validate.yml b/ansible/roles/murano/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..03f5facbb135f4059938be58463ea74181a476d0
--- /dev/null
+++ b/ansible/roles/murano/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ murano_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ murano_config_validation }}"
diff --git a/ansible/roles/neutron/defaults/main.yml b/ansible/roles/neutron/defaults/main.yml
index 6960112025197c68750182da407d86be295bac94..09f6f91bf7c90487303ca8dc418e0c5cf4296f22 100644
--- a/ansible/roles/neutron/defaults/main.yml
+++ b/ansible/roles/neutron/defaults/main.yml
@@ -198,6 +198,33 @@ neutron_services:
         listen_port: "{{ neutron_server_listen_port }}"
         tls_backend: "yes"
 
+####################
+# Config Validate
+####################
+neutron_config_validation:
+  - generator: "/neutron/etc/oslo-config-generator/neutron.conf"
+    config: "/etc/neutron/neutron.conf"
+  - generator: "/neutron/etc/oslo-config-generator/neutron.conf"
+    config: "/etc/neutron/neutron_vpnaas.conf"
+  - generator: "/neutron/etc/oslo-config-generator/ml2_conf.ini"
+    config: "/etc/neutron/plugins/ml2/ml2_conf.ini"
+  - generator: "/neutron/etc/oslo-config-generator/openvswitch_agent.ini"
+    config: "/etc/neutron/plugins/ml2/openvswitch_agent.ini"
+  - generator: "/neutron/etc/oslo-config-generator/metering_agent.ini"
+    config: "/etc/neutron/metering_agent.ini"
+  - generator: "/neutron/etc/oslo-config-generator/neutron_ovn_metadata_agent.ini"
+    config: "/etc/neutron/neutron_ovn_metadata_agent.ini"
+  - generator: "/neutron/etc/oslo-config-generator/metadata_agent.ini"
+    config: "/etc/neutron/metadata_agent.ini"
+  - generator: "/neutron/etc/oslo-config-generator/sriov_agent.ini"
+    config: "/etc/neutron/plugins/ml2/sriov_agent.ini"
+  - generator: "/neutron/etc/oslo-config-generator/l3_agent.ini"
+    config: "/etc/neutron/l3_agent.ini"
+  - generator: "/neutron/etc/oslo-config-generator/dhcp_agent.ini"
+    config: "/etc/neutron/dhcp_agent.ini"
+  - generator: "/neutron/etc/oslo-config-generator/linuxbridge_agent.ini"
+    config: "/etc/neutron/plugins/ml2/linuxbridge_agent.ini"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/neutron/tasks/config_validate.yml b/ansible/roles/neutron/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5459c7b0146978a0b65a9a48c17eb506deb0604f
--- /dev/null
+++ b/ansible/roles/neutron/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ neutron_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ neutron_config_validation }}"
diff --git a/ansible/roles/nova-cell/defaults/main.yml b/ansible/roles/nova-cell/defaults/main.yml
index a976c769e4781b0d2e4d76c5ad7fb2d4f63775e9..0eead7ffb587667cb7425e1c887b1f1adde52d80 100644
--- a/ansible/roles/nova-cell/defaults/main.yml
+++ b/ansible/roles/nova-cell/defaults/main.yml
@@ -71,6 +71,13 @@ nova_cell_services:
     dimensions: "{{ nova_compute_ironic_dimensions }}"
     healthcheck: "{{ nova_compute_ironic_healthcheck }}"
 
+####################
+# Config Validate
+####################
+nova_cell_config_validation:
+  - generator: "/nova/etc/nova/nova-config-generator.conf"
+    config: "/etc/nova/nova.conf"
+
 ####################
 # Ceph options
 ####################
diff --git a/ansible/roles/nova-cell/tasks/config_validate.yml b/ansible/roles/nova-cell/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..70ed89f91a414b763e127de8a9a02ac6844754cf
--- /dev/null
+++ b/ansible/roles/nova-cell/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ nova_cell_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ nova_cell_config_validation }}"
diff --git a/ansible/roles/nova/defaults/main.yml b/ansible/roles/nova/defaults/main.yml
index b6a23e2f9d6adb934e5a1f7dc373256aebc2fb79..dad4ab678d92643c55e9310dc6d0274ea7899c9f 100644
--- a/ansible/roles/nova/defaults/main.yml
+++ b/ansible/roles/nova/defaults/main.yml
@@ -55,6 +55,13 @@ nova_services:
     dimensions: "{{ nova_super_conductor_dimensions }}"
     healthcheck: "{{ nova_super_conductor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+nova_config_validation:
+  - generator: "/nova/etc/nova/nova-config-generator.conf"
+    config: "/etc/nova/nova.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/nova/tasks/config_validate.yml b/ansible/roles/nova/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8f011d3ecb07583ca6ffe1253abbd7247da77d0a
--- /dev/null
+++ b/ansible/roles/nova/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ nova_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ nova_config_validation }}"
diff --git a/ansible/roles/octavia/defaults/main.yml b/ansible/roles/octavia/defaults/main.yml
index ae428d4c78d323fd3ba283879b9ff4b61c305777..49c502b4368df14c9ba55c8322901a97b4d98a9d 100644
--- a/ansible/roles/octavia/defaults/main.yml
+++ b/ansible/roles/octavia/defaults/main.yml
@@ -62,6 +62,12 @@ octavia_required_roles:
   - load-balancer_admin
   - load-balancer_quota_admin
 
+####################
+# Config Validate
+####################
+octavia_config_validation:
+  - generator: "/octavia/etc/config/octavia-config-generator.conf"
+    config: "/etc/octavia/octavia.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/octavia/tasks/config_validate.yml b/ansible/roles/octavia/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e9069eb7ec0076eddd1b7fd86919c19f015f63fc
--- /dev/null
+++ b/ansible/roles/octavia/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ octavia_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ octavia_config_validation }}"
diff --git a/ansible/roles/opensearch/tasks/config_validate.yml b/ansible/roles/opensearch/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/opensearch/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/openvswitch/tasks/config_validate.yml b/ansible/roles/openvswitch/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/openvswitch/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/ovn-controller/tasks/config_validate.yml b/ansible/roles/ovn-controller/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/ovn-controller/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/ovn-db/tasks/config_validate.yml b/ansible/roles/ovn-db/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/ovn-db/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/ovs-dpdk/tasks/config_validate.yml b/ansible/roles/ovs-dpdk/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/ovs-dpdk/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/placement/defaults/main.yml b/ansible/roles/placement/defaults/main.yml
index a287454e62bce051634cbde785ea7ee4e1c775aa..51c78739bdc5d2dfba6167c536cc78ac1c4ba18e 100644
--- a/ansible/roles/placement/defaults/main.yml
+++ b/ansible/roles/placement/defaults/main.yml
@@ -24,6 +24,13 @@ placement_services:
         listen_port: "{{ placement_api_listen_port }}"
         tls_backend: "{{ placement_enable_tls_backend }}"
 
+####################
+# Config Validate
+####################
+placement_config_validation:
+  - generator: "/placement/etc/placement/config-generator.conf"
+    config: "/etc/placement/placement.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/placement/tasks/config_validate.yml b/ansible/roles/placement/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9411eb44a4c6f2e1f0fb8b4b20361a3d9fef9ad6
--- /dev/null
+++ b/ansible/roles/placement/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ placement_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ placement_config_validation }}"
diff --git a/ansible/roles/prometheus/tasks/config_validate.yml b/ansible/roles/prometheus/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/prometheus/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/rabbitmq/tasks/config_validate.yml b/ansible/roles/rabbitmq/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/rabbitmq/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/redis/tasks/config_validate.yml b/ansible/roles/redis/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/redis/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/sahara/defaults/main.yml b/ansible/roles/sahara/defaults/main.yml
index 7d746c23b16b29d2ffad7cd9b1dc124e0ee2af53..dadea0f294ba68208e5684f6991560be859f3307 100644
--- a/ansible/roles/sahara/defaults/main.yml
+++ b/ansible/roles/sahara/defaults/main.yml
@@ -29,6 +29,12 @@ sahara_services:
     dimensions: "{{ sahara_engine_dimensions }}"
     healthcheck: "{{ sahara_engine_healthcheck }}"
 
+####################
+# Config Validate
+####################
+sahara_config_validation:
+  - generator: "/sahara/tools/config/config-generator.sahara.conf"
+    config: "/etc/sahara/sahara.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/sahara/tasks/config_validate.yml b/ansible/roles/sahara/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ea503b9d88bd3aa262be3dcef8b25595bb4ae349
--- /dev/null
+++ b/ansible/roles/sahara/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ sahara_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ sahara_config_validation }}"
diff --git a/ansible/roles/senlin/defaults/main.yml b/ansible/roles/senlin/defaults/main.yml
index ded678fb34f1668a0c698591917ee7f4a2979a20..b1bfa11082c183fc3b8b8fa6d1b79a7ca2f36abf 100644
--- a/ansible/roles/senlin/defaults/main.yml
+++ b/ansible/roles/senlin/defaults/main.yml
@@ -46,6 +46,13 @@ senlin_services:
     dimensions: "{{ senlin_health_manager_dimensions }}"
     healthcheck: "{{ senlin_health_manager_healthcheck }}"
 
+####################
+# Config Validate
+####################
+senlin_config_validation:
+  - generator: "/senlin/tools/config-generator.conf"
+    config: "/etc/senlin/senlin.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/senlin/tasks/config_validate.yml b/ansible/roles/senlin/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f8019a5e072ecd368b7383ff93c9acfeb4556e18
--- /dev/null
+++ b/ansible/roles/senlin/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ senlin_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ senlin_config_validation }}"
diff --git a/ansible/roles/service-config-validate/defaults/main.yml b/ansible/roles/service-config-validate/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..933689f8bc48a8c71f35518f0e1d5d9debaf82b9
--- /dev/null
+++ b/ansible/roles/service-config-validate/defaults/main.yml
@@ -0,0 +1,6 @@
+---
+# Common role for config-validates.
+
+# Dict of services.
+service_config_validate_output_dir: "/var/log/kolla/config-validate"
+service_config_validate_services: {}
diff --git a/ansible/roles/service-config-validate/tasks/main.yml b/ansible/roles/service-config-validate/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ae2cbe2ea3dbee7e787ea19a360594eb27a3dd18
--- /dev/null
+++ b/ansible/roles/service-config-validate/tasks/main.yml
@@ -0,0 +1,13 @@
+---
+- name: "{{ project_name }} | Validate configurations for each service"
+  vars:
+    service_name: "{{ outer_item.key }}"
+    service: "{{ outer_item.value }}"
+    output_dir: "{{ service_config_validate_output_dir }}/{{ inventory_hostname }}/{{ project_name }}/{{ service_name }}"
+  include_tasks: validate.yml
+  loop: "{{ query('dict', service_config_validate_services | select_services_enabled_and_mapped_to_host) }}"
+  loop_control:
+    label: "{{ service_name }}"
+    loop_var: outer_item
+  when:
+    - service_config_validation is defined
diff --git a/ansible/roles/service-config-validate/tasks/validate.yml b/ansible/roles/service-config-validate/tasks/validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a327277fe00f3e84ee7e9ea62dc0075bd5f19b43
--- /dev/null
+++ b/ansible/roles/service-config-validate/tasks/validate.yml
@@ -0,0 +1,49 @@
+---
+- name: "{{ project_name }} : {{ service.container_name }} | Get info on container"
+  become: True
+  kolla_container_facts:
+    container_engine: "{{ kolla_container_engine }}"
+    name:
+      - "{{ service.container_name }}"
+  register: container_info
+
+- name: "{{ project_name }} : {{ service.container_name }} | Validate configurations"
+  become: True
+  command: >
+    {{ kolla_container_engine }} exec {{ service.container_name }}
+    bash -c "[[ -f {{ inner_item['config'] }} ]] && oslo-config-validator --config-file {{ inner_item['generator'] }} --input-file {{ inner_item['config'] }}"
+  when:
+    - container_info._containers | length > 0
+  register: result
+  failed_when: result.rc not in [0, 1]  # rc 1 is expected when errors are found in the config file, or when the config file doesn't exist
+  with_items: "{{ service_config_validation }}"
+  loop_control:
+    label: "{{ inner_item['config'] | basename }}"
+    loop_var: inner_item
+  changed_when: False
+
+- name: "{{ project_name }} : {{ service.container_name }} | Ensure log directory exists"
+  become: True
+  file:
+    path: "{{ output_dir }}"
+    state: directory
+  when:
+    - result.results | map(attribute='rc', default=0) | select('equalto', 1) | list | length > 0
+    - result.results | map(attribute='stderr', default="") | select('ne', "") | list | length > 0
+  delegate_to: localhost
+
+- name: "{{ project_name }} : {{ service.container_name }} | Log configuration errors"
+  become: True
+  copy:
+    content: "{{ inner_item.stderr }}"
+    dest: "{{ output_dir }}/{{ inner_item.inner_item.config | basename }}.err"
+  when:
+    - container_info._containers | length > 0
+    - inner_item.rc is defined
+    - inner_item.rc == 1
+    - inner_item.stderr != ""
+  loop: "{{ result.results }}"
+  loop_control:
+    label: "{{ inner_item.inner_item.config | basename }}"
+    loop_var: inner_item
+  delegate_to: localhost
diff --git a/ansible/roles/skydive/tasks/config_validate.yml b/ansible/roles/skydive/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/skydive/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/solum/defaults/main.yml b/ansible/roles/solum/defaults/main.yml
index 766dea8ec4354641c691f9cefcd42ee0e4046e2c..4af0633a66b96f13515bbb63440ad010d5465a17 100644
--- a/ansible/roles/solum/defaults/main.yml
+++ b/ansible/roles/solum/defaults/main.yml
@@ -58,6 +58,13 @@ solum_services:
     dimensions: "{{ solum_conductor_dimensions }}"
     healthcheck: "{{ solum_conductor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+solum_config_validation:
+  - generator: "/solum/etc/solum/config-generator.conf"
+    config: "/etc/solum/solum.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/solum/tasks/config_validate.yml b/ansible/roles/solum/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..05ecc13b6a126d614ed2db395a4b9b84ae79f8af
--- /dev/null
+++ b/ansible/roles/solum/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ solum_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ solum_config_validation }}"
diff --git a/ansible/roles/storm/tasks/config_validate.yml b/ansible/roles/storm/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/storm/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/swift/tasks/config_validate.yml b/ansible/roles/swift/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/swift/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/tacker/defaults/main.yml b/ansible/roles/tacker/defaults/main.yml
index 8ec82337878af25611a9bc8cef0b2cc84722ae01..daa9980b0af0a0d2a7ad997b9a6a5388fba768ed 100644
--- a/ansible/roles/tacker/defaults/main.yml
+++ b/ansible/roles/tacker/defaults/main.yml
@@ -32,6 +32,13 @@ tacker_services:
     dimensions: "{{ tacker_conductor_dimensions }}"
     healthcheck: "{{ tacker_conductor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+tacker_config_validation:
+  - generator: "/tacker/etc/config-generator.conf"
+    config: "/etc/tacker/tacker.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/tacker/tasks/config_validate.yml b/ansible/roles/tacker/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cc200fdbac7407c014add68953a39d0bcf5378a7
--- /dev/null
+++ b/ansible/roles/tacker/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ tacker_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ tacker_config_validation }}"
diff --git a/ansible/roles/telegraf/tasks/config_validate.yml b/ansible/roles/telegraf/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/telegraf/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/trove/defaults/main.yml b/ansible/roles/trove/defaults/main.yml
index 1971f4a36a65fe3a5850cc2783071de3058dc0ab..455849ff370ce3c9a39bd29ff230a4738db4f003 100644
--- a/ansible/roles/trove/defaults/main.yml
+++ b/ansible/roles/trove/defaults/main.yml
@@ -36,6 +36,12 @@ trove_services:
     dimensions: "{{ trove_taskmanager_dimensions }}"
     healthcheck: "{{ trove_taskmanager_healthcheck }}"
 
+####################
+# Config Validate
+####################
+trove_config_validation:
+  - generator: "/trove/tools/trove-config-generator.conf"
+    config: "/etc/trove/trove.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/trove/tasks/config_validate.yml b/ansible/roles/trove/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b8c4c0166ead14484ff1f2c74728be6b2c426003
--- /dev/null
+++ b/ansible/roles/trove/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ trove_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ trove_config_validation }}"
diff --git a/ansible/roles/venus/defaults/main.yml b/ansible/roles/venus/defaults/main.yml
index a1a7021a11a2295a08a39a413eff855aa1cf87f6..d2d044f5926b4cdf3f7903487e34c92a249e8448 100644
--- a/ansible/roles/venus/defaults/main.yml
+++ b/ansible/roles/venus/defaults/main.yml
@@ -27,6 +27,13 @@ venus_services:
     volumes: "{{ venus_manager_default_volumes + venus_manager_extra_volumes }}"
     dimensions: "{{ venus_manager_dimensions }}"
 
+####################
+# Config Validate
+####################
+venus_config_validation:
+  - generator: "/venus/tools/config/venus-config-generator.conf"
+    config: "/etc/venus/venus.conf"
+
 ####################
 # Database
 ####################
diff --git a/ansible/roles/venus/tasks/config_validate.yml b/ansible/roles/venus/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..57ab862017a2cefbaea21242cfb12717930dd2e5
--- /dev/null
+++ b/ansible/roles/venus/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ venus_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ venus_config_validation }}"
diff --git a/ansible/roles/vitrage/defaults/main.yml b/ansible/roles/vitrage/defaults/main.yml
index bbe74ebf5c382a3d256bac528ca1118fc67b0bbb..8e192d784de4becf1b403a7342ab59f6092b0d8a 100644
--- a/ansible/roles/vitrage/defaults/main.yml
+++ b/ansible/roles/vitrage/defaults/main.yml
@@ -52,6 +52,13 @@ vitrage_services:
     dimensions: "{{ vitrage_persistor_dimensions }}"
     healthcheck: "{{ vitrage_persistor_healthcheck }}"
 
+####################
+# Config Validate
+####################
+vitrage_config_validation:
+  - generator: "/vitrage/etc/vitrage/vitrage-config-generator.conf"
+    config: "/etc/vitrage/vitrage.conf"
+
 ####################
 ## Database
 #####################
diff --git a/ansible/roles/vitrage/tasks/config_validate.yml b/ansible/roles/vitrage/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..307e5b0bccd407e8d4248276cf75d4ffe71e1334
--- /dev/null
+++ b/ansible/roles/vitrage/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ vitrage_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ vitrage_config_validation }}"
diff --git a/ansible/roles/watcher/defaults/main.yml b/ansible/roles/watcher/defaults/main.yml
index 35df766ecb2b3dc784c3ddf4ab2ddac0c4e3fa13..03f3445536e19a1dbc2fe136f93d490a25cf858e 100644
--- a/ansible/roles/watcher/defaults/main.yml
+++ b/ansible/roles/watcher/defaults/main.yml
@@ -36,6 +36,12 @@ watcher_services:
     dimensions: "{{ watcher_engine_dimensions }}"
     healthcheck: "{{ watcher_engine_healthcheck }}"
 
+####################
+# Config Validate
+####################
+watcher_config_validation:
+  - generator: "/watcher/etc/watcher/oslo-config-generator/watcher.conf"
+    config: "/etc/watcher/watcher.conf"
 
 ####################
 # Database
diff --git a/ansible/roles/watcher/tasks/config_validate.yml b/ansible/roles/watcher/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1e74980f5a00b4dd69e1f703a18200efd90171d1
--- /dev/null
+++ b/ansible/roles/watcher/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ watcher_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ watcher_config_validation }}"
diff --git a/ansible/roles/zookeeper/tasks/config_validate.yml b/ansible/roles/zookeeper/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed97d539c095cf1413af30cc23dea272095b97dd
--- /dev/null
+++ b/ansible/roles/zookeeper/tasks/config_validate.yml
@@ -0,0 +1 @@
+---
diff --git a/ansible/roles/zun/defaults/main.yml b/ansible/roles/zun/defaults/main.yml
index edb727c9caaa83c6c6f006b8b8e9ad047b215101..61719a179e6d06c5512bd7475234b846e0ebda14 100644
--- a/ansible/roles/zun/defaults/main.yml
+++ b/ansible/roles/zun/defaults/main.yml
@@ -57,6 +57,13 @@ zun_services:
     dimensions: "{{ zun_cni_daemon_dimensions }}"
     healthcheck: "{{ zun_cni_daemon_healthcheck }}"
 
+####################
+# Config Validate
+####################
+zun_config_validation:
+  - generator: "/zun/etc/zun/zun-config-generator.conf"
+    config: "/etc/zun/zun.conf"
+
 ####################
 ## Database
 ####################
diff --git a/ansible/roles/zun/tasks/config_validate.yml b/ansible/roles/zun/tasks/config_validate.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9803248961b94accd6ca8cbddafc45df810d92e1
--- /dev/null
+++ b/ansible/roles/zun/tasks/config_validate.yml
@@ -0,0 +1,7 @@
+---
+- import_role:
+    name: service-config-validate
+  vars:
+    service_config_validate_services: "{{ zun_services }}"
+    service_name: "{{ project_name }}"
+    service_config_validation: "{{ zun_config_validation }}"
diff --git a/releasenotes/notes/integrate-oslo-config-validator-4dc26b8753984917.yaml b/releasenotes/notes/integrate-oslo-config-validator-4dc26b8753984917.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..43809300fd78eff75f5fe9b4fae89e92f762502c
--- /dev/null
+++ b/releasenotes/notes/integrate-oslo-config-validator-4dc26b8753984917.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    Adds the command ``kolla-ansible validate-config``. This runs
+    ``oslo-config-validator`` against the configurgation files present in the
+    deployed OpenStack services. By default, results are saved to
+    ``/var/log/kolla/config-validate``
diff --git a/tools/kolla-ansible b/tools/kolla-ansible
index 861faec745e75600367cec566d921e6c2604a014..3766db61710ded5d3a7a5c58a3592dfd0c6f9a29 100755
--- a/tools/kolla-ansible
+++ b/tools/kolla-ansible
@@ -200,6 +200,7 @@ Commands:
     upgrade              Upgrades existing OpenStack Environment
     upgrade-bifrost      Upgrades an existing bifrost container
     genconfig            Generate configuration files for enabled OpenStack services
+    validate-config      Validate configuration files for enabled OpenStack services
     prune-images         Prune orphaned Kolla images
     nova-libvirt-cleanup Clean up disabled nova_libvirt containers
 EOF
@@ -246,6 +247,7 @@ octavia-certificates
 upgrade
 upgrade-bifrost
 genconfig
+validate-config
 prune-images
 nova-libvirt-cleanup
 EOF
@@ -535,6 +537,10 @@ EOF
         ACTION="Generate configuration files for enabled OpenStack services"
         EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=config"
         ;;
+(validate-config)
+        ACTION="Validate configuration files for enabled OpenStack services"
+        EXTRA_OPTS="$EXTRA_OPTS -e kolla_action=config_validate"
+        ;;
 (prune-images)
         ACTION="Prune orphaned Kolla images"
         PLAYBOOK="${BASEDIR}/ansible/prune-images.yml"