return '\n'.join(tmp_patch)
 
 
+def is_path_in_patch(patch, path):
+    """
+    Checks if a particular path is modified in a patch diff
+    :param patch: patch diff
+    :param path: path to check for in diff
+    :return: Boolean
+    """
+    for line in patch.split("\n"):
+        if re.match('^diff.*{}'.format(path), line):
+            return True
+    return False
+
+
 def get_patch(change_id, repo, branch, url=con.OPENSTACK_GERRIT):
     logging.info("Fetching patch for change id {}".format(change_id))
     change = get_change(url, repo, branch, change_id)
 
 from apex.virtual import utils as virt_utils
 
 
-def project_to_path(project):
+def project_to_path(project, patch=None):
     """
     Translates project to absolute file path to use in patching
     :param project: name of project
+    :param patch: the patch to applied to the project
     :return: File path
     """
     if project.startswith('openstack/'):
         return "/etc/puppet/modules/{}".format(project.replace('puppet-', ''))
     elif 'tripleo-heat-templates' in project:
         return "/usr/share/openstack-tripleo-heat-templates"
+    elif ('tripleo-common' in project and
+          build_utils.is_path_in_patch(patch, 'container-images/')):
+        # tripleo-common has python and another component to it
+        # here we detect if there is a change to the yaml component and if so
+        # treat it like it is not python. This has the caveat of if there
+        # is a patch to both python and yaml this will not work
+        # FIXME(trozet): add ability to split tripleo-common patches that
+        # modify both python and yaml
+        return "/usr/share/openstack-tripleo-common-containers/"
     else:
         # assume python.  python patches will apply to a project name subdir.
         # For example, python-tripleoclient patch will apply to the
             branch = default_branch
         patch_diff = build_utils.get_patch(patch['change-id'],
                                            patch['project'], branch)
-        project_path = project_to_path(patch['project'])
+        project_path = project_to_path(patch['project'], patch_diff)
         # If docker tag and python we know this patch belongs on docker
         # container for a docker service. Therefore we build the dockerfile
         # and move the patch into the containers directory.  We also assume
 
     'neutron-opendaylight-sriov.yaml': None,
     'neutron-bgpvpn-opendaylight.yaml': None,
     'neutron-sfc-opendaylight.yaml': None,
-    'neutron-ml2-ovn.yaml': 'neutron-ovn.yaml'
+    'neutron-ml2-ovn.yaml': 'neutron-ovn-ha.yaml'
 }
 DOCKERHUB_OOO = 'https://registry.hub.docker.com/v2/repositories' \
                 '/tripleomaster/'
 
         self.assertNotRegex(tmp_patch, 'Steps of upgrade are as follows')
         self.assertNotRegex(tmp_patch, 'Steps invlolved in level 2 update')
 
+    def test_is_path_in_patch(self):
+        with open(os.path.join(con.TEST_DUMMY_CONFIG, '98faaca.diff')) as fh:
+            dummy_patch = fh.read()
+        self.assertTrue(build_utils.is_path_in_patch(dummy_patch,
+                                                     'releasenotes/'))
+
     def test_strip_no_patch_sections(self):
         with open(os.path.join(con.TEST_DUMMY_CONFIG, '98faaca.diff')) as fh:
             dummy_patch = fh.read()
 
 %{_sysconfdir}/opnfv-apex/os-odl-sriov-ha.yaml
 %{_sysconfdir}/opnfv-apex/os-odl-sriov-noha.yaml
 %{_sysconfdir}/opnfv-apex/os-odl-gluon-noha.yaml
-%{_sysconfdir}/opnfv-apex/os-ovn-nofeature-noha.yaml
+%{_sysconfdir}/opnfv-apex/os-ovn-nofeature-ha.yaml
+%{_sysconfdir}/opnfv-apex/os-ovn-queens-ha.yaml
 %{_sysconfdir}/opnfv-apex/os-onos-nofeature-ha.yaml
 %{_sysconfdir}/opnfv-apex/os-onos-sfc-ha.yaml
 %{_sysconfdir}/opnfv-apex/os-ocl-nofeature-ha.yaml
 %doc %{_docdir}/opnfv/inventory.yaml.example
 
 %changelog
+* Thu Sep 27 2018 Tim Rozet <trozet@redhat.com> - 7.0-8
+  Adds OVN HA and Queens scenario
 * Fri Aug 24 2018 Tim Rozet <trozet@redhat.com> - 7.0-7
   Add Calipso for Queens
 * Tue Aug 21 2018 Ricardo Noriega <rnoriega@redhat.com> - 7.0-6
 
--- /dev/null
+---
+global_params:
+  ha_enabled: true
+  patches:
+    undercloud:
+      - change-id: Ic08ff58b10d4fa7116163be1f7fce57879cee8c5
+        project: openstack/tripleo-common
+
+deploy_options:
+  containers: true
+  sdn_controller: ovn
+  tacker: false
+  congress: false
+  sfc: false
+  vpn: false
 
+++ /dev/null
----
-global_params:
-  ha_enabled: false
-
-deploy_options:
-  sdn_controller: ovn
-  tacker: false
-  congress: true
-  sfc: false
-  vpn: false
 
--- /dev/null
+---
+global_params:
+  ha_enabled: true
+  patches:
+    undercloud:
+      - change-id: Ic08ff58b10d4fa7116163be1f7fce57879cee8c5
+        project: openstack/tripleo-common
+        branch: master
+
+deploy_options:
+  containers: true
+  os_version: queens
+  sdn_controller: ovn
+  tacker: false
+  congress: false
+  sfc: false
+  vpn: false
 
         crudini --set /var/lib/config-data/puppet-generated/neutron/etc/neutron/metadata_agent.ini
         DEFAULT nova_metadata_host $(hiera -c /etc/puppet/hiera.yaml nova_metadata_vip)
       become: yes
-      when: "'controller' in ansible_hostname"
+      when:
+        - "'controller' in ansible_hostname"
+        - sdn != 'ovn'
     - name: Restart metadata service
       shell: "docker restart neutron_metadata_agent"
       become: yes
       when:
         - "'controller' in ansible_hostname"
+        - sdn != 'ovn'