diff --git a/ansible/roles/neutron/tasks/deploy.yml b/ansible/roles/neutron/tasks/deploy.yml
index 49d79e20d85f539d622e3bba5e4f48c5e1bd7e42..68a1f941d7d2ae3a34d211c31cf9428a50b005b6 100644
--- a/ansible/roles/neutron/tasks/deploy.yml
+++ b/ansible/roles/neutron/tasks/deploy.yml
@@ -1,4 +1,6 @@
 ---
+- import_tasks: neutron_plugin_agent_check.yml
+
 - import_tasks: register.yml
 
 - include_tasks: clone.yml
diff --git a/ansible/roles/neutron/tasks/neutron_plugin_agent_check.yml b/ansible/roles/neutron/tasks/neutron_plugin_agent_check.yml
new file mode 100644
index 0000000000000000000000000000000000000000..931a2c5f419d09fe08875cec6476b71653f18a28
--- /dev/null
+++ b/ansible/roles/neutron/tasks/neutron_plugin_agent_check.yml
@@ -0,0 +1,35 @@
+---
+- name: Get container facts
+  become: true
+  kolla_container_facts:
+    container_engine: "{{ kolla_container_engine }}"
+    name:
+      - neutron_openvswitch_agent
+      - ovn_controller
+  check_mode: false
+  register: container_facts
+
+- name: Get container volume facts
+  become: true
+  kolla_container_volume_facts:
+    container_engine: "{{ kolla_container_engine }}"
+    name:
+      - ovn_nb_db
+      - ovn_sb_db
+  check_mode: false
+  register: container_volume_facts
+
+- name: Check for ML2/OVN presence
+  assert:
+    that: neutron_plugin_agent == 'ovn'
+    fail_msg: "ML2/OVN agent detected, neutron_plugin_agent is not set to 'ovn', Kolla-Ansible does not support this migration operation."
+  when: (container_facts['ovn_controller'] is defined) or (container_volume_facts['ovn_nb_db'] is defined) or (container_volume_facts['ovn_sb_db'] is defined)
+
+- name: Check for ML2/OVS presence
+  assert:
+    that:
+      - neutron_plugin_agent == 'openvswitch'
+      - container_volume_facts['ovn_nb_db'] is not defined
+      - container_volume_facts['ovn_sb_db'] is not defined
+    fail_msg: "ML2/OVS agent detected, neutron_plugin_agent is not set to 'openvswitch', Kolla-Ansible does not support this migration operation."
+  when: container_facts['neutron_openvswitch_agent'] is defined
diff --git a/ansible/roles/neutron/tasks/precheck.yml b/ansible/roles/neutron/tasks/precheck.yml
index 27d2a48920bd34b6fffabf933aa2102e69990174..715f4843f94c99c7ac69f19287ea3e98384c5b86 100644
--- a/ansible/roles/neutron/tasks/precheck.yml
+++ b/ansible/roles/neutron/tasks/precheck.yml
@@ -53,3 +53,5 @@
   run_once: True
   when:
     - enable_ironic_neutron_agent | bool
+
+- import_tasks: neutron_plugin_agent_check.yml
diff --git a/ansible/roles/neutron/tasks/upgrade.yml b/ansible/roles/neutron/tasks/upgrade.yml
index 9e9355b7da6fa208e399653b43726821fdec30b1..9c223bc27c31646f2ed3e67f3bef837137eba799 100644
--- a/ansible/roles/neutron/tasks/upgrade.yml
+++ b/ansible/roles/neutron/tasks/upgrade.yml
@@ -1,4 +1,6 @@
 ---
+- import_tasks: neutron_plugin_agent_check.yml
+
 - include_tasks: rolling_upgrade.yml
   when: neutron_enable_rolling_upgrade | bool
 
diff --git a/releasenotes/notes/ml2ovs_precheck-c859504004f6884b.yaml b/releasenotes/notes/ml2ovs_precheck-c859504004f6884b.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a1b922616d84cd5f54af0faa97b851301b61d928
--- /dev/null
+++ b/releasenotes/notes/ml2ovs_precheck-c859504004f6884b.yaml
@@ -0,0 +1,9 @@
+---
+features:
+  - |
+    Added a neutron check for ML2/OVS and ML2/OVN presence
+    at the start of deploy phase. It will fail if
+    neutron_plugin_agent is set to ``ovn`` and use of ML2/OVS
+    container detected. In case where neutron_plugin_agent
+    is set to ``openvswitch`` the check will fail when it detects
+    ML2/OVN container or any of the OVN specific volumes.