Keep fan services running until poweroff completes

All the fan services associated with controlling, monitoring and
presence detection of fans need to remain active until a poweroff
completes. This helps ensure thermal safety while a system is in
transition to a powered off state.

With the introduction of this new target (which runs last in
the power off path), need to move the host reset service to
running after it to ensure the power on in the reboot path
does not start until the last power off target runs.

Resolves openbmc/openbmc#2762

Change-Id: I4ca671d2c7de66e8bfa4bba607b06c88c0a6e7f9
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/common/recipes-core/systemd/obmc-targets.bb b/common/recipes-core/systemd/obmc-targets.bb
index 1061470..26fbcd1 100644
--- a/common/recipes-core/systemd/obmc-targets.bb
+++ b/common/recipes-core/systemd/obmc-targets.bb
@@ -18,9 +18,10 @@
 # Chassis action power targets
 # - on:  Services to run to power on the chassis
 # - off: Services to run to power off the chassis
+# - powered-off: Services to run once chassis power is off
 # - reset: Services to check chassis power state and update chassis "on" target
 # - hard-off: Services to force an immediate power off of the chassis
-CHASSIS_ACTION_TARGETS = "poweron poweroff powerreset hard-poweroff"
+CHASSIS_ACTION_TARGETS = "poweron poweroff powered-off powerreset hard-poweroff"
 
 # Track all host synchronization point targets
 # - start-pre:                 Services to run before we start host boot
diff --git a/common/recipes-core/systemd/obmc-targets/obmc-chassis-powered-off@.target b/common/recipes-core/systemd/obmc-targets/obmc-chassis-powered-off@.target
new file mode 100644
index 0000000..1a042a0
--- /dev/null
+++ b/common/recipes-core/systemd/obmc-targets/obmc-chassis-powered-off@.target
@@ -0,0 +1,9 @@
+[Unit]
+Description=Chassis%i (Powered Off)
+Wants={SYSTEMD_DEFAULT_TARGET}
+After={SYSTEMD_DEFAULT_TARGET}
+Wants=mapper-wait@-xyz-openbmc_project-state-chassis%i.service
+After=mapper-wait@-xyz-openbmc_project-state-chassis%i.service
+Conflicts=obmc-chassis-poweron@%i.target
+Conflicts=obmc-chassis-reset@%i.target
+RefuseManualStop=yes
diff --git a/common/recipes-core/systemd/obmc-targets/obmc-fan-control-ready@.target b/common/recipes-core/systemd/obmc-targets/obmc-fan-control-ready@.target
index 6957b1b..e041a55 100644
--- a/common/recipes-core/systemd/obmc-targets/obmc-fan-control-ready@.target
+++ b/common/recipes-core/systemd/obmc-targets/obmc-fan-control-ready@.target
@@ -1,4 +1,4 @@
 [Unit]
 Description=Fan Control Ready
 RefuseManualStop=yes
-Conflicts=obmc-chassis-poweroff@%i.target
+Conflicts=obmc-chassis-powered-off@%i.target
diff --git a/common/recipes-phosphor/chassis/obmc-op-control-power.bb b/common/recipes-phosphor/chassis/obmc-op-control-power.bb
index 5dd6d12..e341463 100644
--- a/common/recipes-phosphor/chassis/obmc-op-control-power.bb
+++ b/common/recipes-phosphor/chassis/obmc-op-control-power.bb
@@ -20,6 +20,7 @@
         op-wait-power-off@.service \
         op-reset-chassis-running@.service \
         op-reset-chassis-on@.service \
+        op-powered-off@.service \
         "
 
 SYSTEMD_ENVIRONMENT_FILE_${PN} += "obmc/power_control"
@@ -34,6 +35,10 @@
 STOP_INSTFMT = "op-power-stop@{0}.service"
 STOP_FMT = "../${STOP_TMPL}:${STOP_TGTFMT}.requires/${STOP_INSTFMT}"
 
+POWERED_OFF_TMPL = "op-powered-off@.service"
+POWERED_OFF_INSTFMT = "op-powered-off@{0}.service"
+POWERED_OFF_FMT = "../${POWERED_OFF_TMPL}:${STOP_TGTFMT}.requires/${POWERED_OFF_INSTFMT}"
+
 ON_TMPL = "op-wait-power-on@.service"
 ON_INSTFMT = "op-wait-power-on@{0}.service"
 ON_FMT = "../${ON_TMPL}:${START_TGTFMT}.requires/${ON_INSTFMT}"
@@ -55,6 +60,7 @@
 # Build up requires relationship for START_TGTFMT and STOP_TGTFMT
 SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'START_FMT', 'OBMC_POWER_INSTANCES', 'OBMC_CHASSIS_INSTANCES')}"
 SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'STOP_FMT', 'OBMC_POWER_INSTANCES', 'OBMC_CHASSIS_INSTANCES')}"
+SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'POWERED_OFF_FMT', 'OBMC_POWER_INSTANCES', 'OBMC_CHASSIS_INSTANCES')}"
 SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'ON_FMT', 'OBMC_POWER_INSTANCES', 'OBMC_CHASSIS_INSTANCES')}"
 SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'OFF_FMT', 'OBMC_POWER_INSTANCES', 'OBMC_CHASSIS_INSTANCES')}"
 SYSTEMD_LINK_${PN} += "${@compose_list_zip(d, 'RESET_ON_FMT', 'OBMC_POWER_INSTANCES', 'OBMC_CHASSIS_INSTANCES')}"
diff --git a/common/recipes-phosphor/chassis/obmc-op-control-power/op-powered-off@.service b/common/recipes-phosphor/chassis/obmc-op-control-power/op-powered-off@.service
new file mode 100644
index 0000000..b76db7b
--- /dev/null
+++ b/common/recipes-phosphor/chassis/obmc-op-control-power/op-powered-off@.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=Power is off to chassis%i
+After=op-wait-power-off@%i.service
+Requires=op-wait-power-off@%i.service
+
+[Service]
+RemainAfterExit=no
+# systemd starts all wanted targets in parallel and a Conflict
+# statement will resolve itself when the target starts, not when
+# completes. Some services have a requirement to stop
+# once power is off. The solution is to create a new target,
+# obmc-chassis-powered-off@.target, that is started after it is
+# verified that power has been removed from the chassis. Then
+# services may conflict with this target to ensure they
+# are stopped at the appropriate time.
+ExecStart=/bin/systemctl start obmc-chassis-powered-off@%i.target
+
+
+[Install]
+WantedBy=obmc-chassis-poweroff@%i.target
diff --git a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control-init@.service b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control-init@.service
index b78457f..96b40f6 100644
--- a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control-init@.service
+++ b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control-init@.service
@@ -2,7 +2,7 @@
 Description=Phosphor Fan Control Initialization
 Wants=obmc-power-on@%i.target
 After=obmc-power-on@%i.target
-Conflicts=obmc-chassis-poweroff@%i.target
+Conflicts=obmc-chassis-powered-off@%i.target
 
 [Service]
 Restart=on-failure
diff --git a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service
index 2aef875..8c5903e 100644
--- a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service
+++ b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-control@.service
@@ -1,6 +1,6 @@
 [Unit]
 Description=Phosphor Fan Control Daemon
-Conflicts=obmc-chassis-poweroff@%i.target
+Conflicts=obmc-chassis-powered-off@%i.target
 
 [Service]
 Restart=on-failure
diff --git a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor-init@.service b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor-init@.service
index a5cfd85..e8a6f69 100644
--- a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor-init@.service
+++ b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor-init@.service
@@ -2,7 +2,7 @@
 Description=Phosphor Fan Monitor Initialization
 Wants=obmc-power-on@%i.target
 After=obmc-power-on@%i.target
-Conflicts=obmc-chassis-poweroff@%i.target
+Conflicts=obmc-chassis-powered-off@%i.target
 
 [Service]
 Restart=on-failure
diff --git a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service
index 09f3494..ddecfba 100644
--- a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service
+++ b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-monitor@.service
@@ -1,6 +1,6 @@
 [Unit]
 Description=Phosphor Fan Monitor Daemon
-Conflicts=obmc-chassis-poweroff@%i.target
+Conflicts=obmc-chassis-powered-off@%i.target
 
 [Service]
 Restart=on-failure
diff --git a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-presence-tach@.service b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-presence-tach@.service
index 07d23d8..a324740 100644
--- a/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-presence-tach@.service
+++ b/common/recipes-phosphor/fans/phosphor-fan/phosphor-fan-presence-tach@.service
@@ -2,7 +2,7 @@
 Description=Phosphor Fan Presence Tach Daemon
 Wants=obmc-power-on@%i.target
 After=obmc-power-on@%i.target
-Conflicts=obmc-chassis-poweroff@%i.target
+Conflicts=obmc-chassis-powered-off@%i.target
 
 [Service]
 Restart=on-failure
diff --git a/common/recipes-phosphor/state/files/phosphor-reboot-host@.service b/common/recipes-phosphor/state/files/phosphor-reboot-host@.service
index fdf84c1..f8f0171 100644
--- a/common/recipes-phosphor/state/files/phosphor-reboot-host@.service
+++ b/common/recipes-phosphor/state/files/phosphor-reboot-host@.service
@@ -4,7 +4,12 @@
 After=obmc-host-stop@%i.target
 
 [Service]
-ExecStart={base_bindir}/systemctl start obmc-host-start@%i.target
+#ExecStart={base_bindir}/systemctl start obmc-host-start@%i.target
+# This service is starting another target that conflicts with the
+# target this service is running in. OpenBMC needs a refactor of
+# how it does its host reset path. Until then, this short term
+# solution does the job.
+ExecStart=/bin/sh -c "sleep 5 && systemctl start obmc-host-start@%i.target"
 
 
 [Install]