diff --git a/environments/undercloud.yaml b/environments/undercloud.yaml
index ca891a1ee7..3341238fb6 100644
--- a/environments/undercloud.yaml
+++ b/environments/undercloud.yaml
@@ -34,6 +34,8 @@ parameter_defaults:
   HeatMaxResourcesPerStack: -1
   HeatMaxJsonBodySize: 2097152
   IronicCleaningDiskErase: 'metadata'
+  IronicCorsAllowedOrigin: '*'
+  IronicDefaultInspectInterface: 'inspector'
   IronicDefaultResourceClass: 'baremetal'
   IronicEnabledHardwareTypes: ['ipmi', 'redfish', 'idrac', 'ilo']
   IronicEnabledBootInterfaces: ['pxe', 'ilo-pxe']
@@ -54,6 +56,8 @@ parameter_defaults:
   IronicEnabledVendorInterfaces: ['ipmitool', 'idrac', 'no-vendor']
   IronicEnableStagingDrivers: true
   IronicCleaningNetwork: 'ctlplane'
+  IronicForcePowerStateDuringSync: false
+  IronicInspectorCollectors: default,extra-hardware,numa-topology,logs
   IronicInspectorInterface: br-ctlplane
   IronicInspectorIpRange: '192.168.24.100,192.168.24.200'
   IronicProvisioningNetwork: 'ctlplane'
diff --git a/puppet/services/ironic-api.yaml b/puppet/services/ironic-api.yaml
index fc22931779..5beb1f06ac 100644
--- a/puppet/services/ironic-api.yaml
+++ b/puppet/services/ironic-api.yaml
@@ -47,10 +47,18 @@ parameters:
       e.g. { ironic-context_is_admin: { key: context_is_admin, value: 'role:admin' } }
     default: {}
     type: json
+  IronicCorsAllowedOrigin:
+    type: string
+    default: ''
+    description: Indicate whether this resource may be shared with the domain received in the request
+                 "origin" header.
   EnableInternalTLS:
     type: boolean
     default: false
 
+conditions:
+  cors_allowed_origin_unset: {equals : [{get_param: IronicCorsAllowedOrigin}, '']}
+
 resources:
   ApacheServiceBase:
     type: ./apache.yaml
@@ -83,6 +91,11 @@ outputs:
         map_merge:
           - get_attr: [IronicBase, role_data, config_settings]
           - get_attr: [ApacheServiceBase, role_data, config_settings]
+          -
+            if:
+            - cors_allowed_origin_unset
+            - {}
+            - ironic::cors::allowed_origin: {get_param: IronicCorsAllowedOrigin}
           - ironic::api::authtoken::password: {get_param: IronicPassword}
             ironic::api::authtoken::project_name: 'service'
             ironic::api::authtoken::user_domain_name: 'Default'
@@ -121,6 +134,11 @@ outputs:
                 params:
                   $NETWORK: {get_param: [ServiceNetMap, IronicApiNetwork]}
             ironic::wsgi::apache::ssl: {get_param: EnableInternalTLS}
+            ironic::cors::max_age: 3600
+            ironic::cors::allow_methods: 'GET,POST,PUT,DELETE,OPTIONS,PATCH'
+            ironic::cors::allow_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token'
+            ironic::cors::expose_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma'
+
             tripleo.ironic_api.firewall_rules:
               '133 ironic api':
                 dport:
diff --git a/puppet/services/ironic-conductor.yaml b/puppet/services/ironic-conductor.yaml
index c1dc814a79..75a5ff2253 100644
--- a/puppet/services/ironic-conductor.yaml
+++ b/puppet/services/ironic-conductor.yaml
@@ -67,6 +67,11 @@ parameters:
                  images). Set to 'netboot' to make the instances boot from
                  controllers using PXE/iPXE.
     type: string
+  IronicDefaultInspectInterface:
+    default: ''
+    description: Inspect interface implementation to use by default. Leave empty to
+                 use the hardware type default.
+    type: string
   IronicDefaultNetworkInterface:
     default: 'flat'
     description: Network interface implementation to use by default.
@@ -164,6 +169,10 @@ parameters:
                  created yet) and should be changed to an actual UUID in
                  a post-deployment stack update.
     type: string
+  IronicForcePowerStateDuringSync:
+    default: true
+    description: Whether to force power state during sync.
+    type: boolean
   MonitoringSubscriptionIronicConductor:
     default: 'overcloud-ironic-conductor'
     type: string
@@ -182,6 +191,7 @@ resources:
       IronicDebug: {get_param: IronicDebug}
 
 conditions:
+  default_inspect_interface_unset: {equals : [{get_param: IronicDefaultInspectInterface}, '']}
   service_debug:
     or:
       - equals: [{get_param: IronicDebug}, 'true']
@@ -198,6 +208,11 @@ outputs:
       config_settings:
         map_merge:
           - get_attr: [IronicBase, role_data, config_settings]
+          -
+            if:
+            - default_inspect_interface_unset
+            - {}
+            - ironic::drivers::interfaces::default_inspect_interface: {get_param: IronicDefaultInspectInterface}
           - ironic::conductor::api_url: {get_param: [EndpointMap, IronicInternal, uri_no_suffix]}
             ironic::conductor::cleaning_disk_erase: {get_param: IronicCleaningDiskErase}
             ironic::conductor::cleaning_network: {get_param: IronicCleaningNetwork}
@@ -206,6 +221,7 @@ outputs:
             ironic::conductor::enabled_drivers: {get_param: IronicEnabledDrivers}
             ironic::conductor::automated_clean: {get_param: IronicAutomatedClean}
             ironic::conductor::enabled_hardware_types: {get_param: IronicEnabledHardwareTypes}
+            ironic::conductor::force_power_state_during_sync: {get_param: IronicForcePowerStateDuringSync}
             # We need an endpoint containing a real IP, not a VIP here
             ironic_conductor_http_host:
               str_replace:
@@ -249,6 +265,8 @@ outputs:
               - service_debug
               - 'always'
               - 'on_failure'
+            # NOTE(emilien): ILO defaulting to UEFI does not match other drivers so bios is used.
+            ironic::drivers::ilo::default_boot_mode: 'bios'
             ironic::drivers::interfaces::enabled_boot_interfaces: {get_param: IronicEnabledBootInterfaces}
             ironic::drivers::interfaces::enabled_console_interfaces: {get_param: IronicEnabledConsoleInterfaces}
             ironic::drivers::interfaces::enabled_deploy_interfaces: {get_param: IronicEnabledDeployInterfaces}
diff --git a/puppet/services/ironic-inspector.yaml b/puppet/services/ironic-inspector.yaml
index 3ce3a8471e..449b4a0a69 100644
--- a/puppet/services/ironic-inspector.yaml
+++ b/puppet/services/ironic-inspector.yaml
@@ -135,6 +135,11 @@ outputs:
             ironic::inspector::authtoken::project_name: 'service'
             ironic::inspector::authtoken::user_domain_name: 'Default'
             ironic::inspector::authtoken::project_domain_name: 'Default'
+            ironic::inspector::cors::allowed_origin: '*'
+            ironic::inspector::cors::max_age: 3600
+            ironic::inspector::cors::allow_methods: 'GET,POST,PUT,DELETE,OPTIONS,PATCH'
+            ironic::inspector::cors::allow_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token'
+            ironic::inspector::cors::expose_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma'
             tripleo.ironic_inspector.firewall_rules:
               '137 ironic-inspector':
                 dport:
diff --git a/puppet/services/tripleo-ui.yaml b/puppet/services/tripleo-ui.yaml
index 4e73a48819..5e7363bdbf 100644
--- a/puppet/services/tripleo-ui.yaml
+++ b/puppet/services/tripleo-ui.yaml
@@ -65,16 +65,6 @@ outputs:
         map_merge:
           - get_attr: [ApacheServiceBase, role_data, config_settings]
           - keystone::cors::allowed_origin: '*'
-            ironic::cors::allowed_origin: '*'
-            ironic::cors::max_age: 3600
-            ironic::cors::allow_methods: 'GET,POST,PUT,DELETE,OPTIONS,PATCH'
-            ironic::cors::allow_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token'
-            ironic::cors::expose_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma'
-            ironic::inspector::cors::allowed_origin: '*'
-            ironic::inspector::cors::max_age: 3600
-            ironic::inspector::cors::allow_methods: 'GET,POST,PUT,DELETE,OPTIONS,PATCH'
-            ironic::inspector::cors::allow_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token'
-            ironic::inspector::cors::expose_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma'
             heat::cors::allowed_origin: '*'
             heat::cors::max_age: 3600
             heat::cors::allow_headers: 'Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma,X-Auth-Token'