phosphor-state-manager: Support multi-host for persist files

phosphor-host-state-manager and phosphor-chassis-state-manager store
informations in files then restore that on service starting.
Since state-managers already change to multi-host now, information
should store into different files from each service instance.

forbackward capability, if there are legacy persist file exist,
rename it to the new file format of instance ;0',i.e, rename files:
'requestedHostTransition' to 'host0-PersistData',
'POHCounter' to 'chassis-POHCounter',
'chassisStateChangeTime' to 'chassis0-StateChangeTime'

Changes:
a.phosphor-host-state-manager:
'/var/lib/phosphor-state-manager/requestedHostTransition'
this file not only store requestedHostTransition now,
rename to PersistData and add host-N prefix for each service.
For example, bus xyz.openbmc_project.State.Host1 store data to
'/var/lib/phosphor-state-manager/host1-PersistData'
 xyz.openbmc_project.State.Host2 store date to
'/var/lib/phosphor-state-manager/host2-PersistData'

b.phosphor-chassis-state-manager:

There are two files to store informations
'/var/lib/phosphor-state-manager/POHCounter',
'/var/lib/phosphor-state-manager/chassisStateChangeTime'
change to:
'/var/lib/phosphor-state-manager/chassis1-POHCounter',
'/var/lib/phosphor-state-manager/chassis2-POHCounter'
...
'/var/lib/phosphor-state-manager/chassis1-StateChangeTime'
'/var/lib/phosphor-state-manager/chassis2-StateChangeTime'
...  for each service.

Tested on Bletchley HW,

set xyz.openbmc_project.State.Host1 RequestedHostTransition to On
'busctl set-property xyz.openbmc_project.State.Host1 /xyz/openbmc_project/state/host1
	xyz.openbmc_project.State.Host RequestedHostTransition s "xyz.openbmc_project.State.Host.Transition.On"'

This request will store in file:
'cat /var/lib/phosphor-state-manager/host1-PersistData'
{
    "value0": {
        "cereal_class_version": 1,
        "value0": "xyz.openbmc_project.State.Host.Transition.On",
        "value1": "xyz.openbmc_project.State.Boot.Progress.ProgressStages.Unspecified",
        "value2": "xyz.openbmc_project.State.OperatingSystem.Status.OSStatus.Inactive"
    }

restart xyz.openbmc_project.State.Host1~Host6 or reboot BMC, 'RequestedHostTransition' for host1 still "On"
'busctl get-property xyz.openbmc_project.State.Host1 /xyz/openbmc_project/state/host1
	xyz.openbmc_project.State.Host RequestedHostTransition'
s "xyz.openbmc_project.State.Host.Transition.On"
'RequestedHostTransition' of the rest 5 Hosts are default value  "xyz.openbmc_project.State.Host.Transition.Off"

Also, set POHCounter of xyz.openbmc_project.State.Chassis2
'busctl set-property xyz.openbmc_project.State.Chassis2	/xyz/openbmc_project/state/chassis2
	xyz.openbmc_project.State.PowerOnHours POHCounter u 5'
it will restore after service restart or BMC reboot,
'busctl get-property  xyz.openbmc_project.State.Chassis2 /xyz/openbmc_project/state/chassis2
	xyz.openbmc_project.State.PowerOnHours POHCounter'
u 5

Change-Id: I739c62707bb805e7c25f399a2fea06beee5543a0
Signed-off-by: Allen.Wang <Allen_Wang@quantatw.com>
diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp
index f3e8389..d526358 100644
--- a/chassis_state_manager.cpp
+++ b/chassis_state_manager.cpp
@@ -605,7 +605,7 @@
 void Chassis::restorePOHCounter()
 {
     uint32_t counter;
-    if (!deserializePOH(POH_COUNTER_PERSIST_PATH, counter))
+    if (!deserializePOH(counter))
     {
         // set to default value
         pohCounter(0);
@@ -616,16 +616,18 @@
     }
 }
 
-fs::path Chassis::serializePOH(const fs::path& path)
+fs::path Chassis::serializePOH()
 {
+    fs::path path{fmt::format(POH_COUNTER_PERSIST_PATH, id)};
     std::ofstream os(path.c_str(), std::ios::binary);
     cereal::JSONOutputArchive oarchive(os);
     oarchive(pohCounter());
     return path;
 }
 
-bool Chassis::deserializePOH(const fs::path& path, uint32_t& pohCounter)
+bool Chassis::deserializePOH(uint32_t& pohCounter)
 {
+    fs::path path{fmt::format(POH_COUNTER_PERSIST_PATH, id)};
     try
     {
         if (fs::exists(path))
@@ -672,7 +674,7 @@
 
 void Chassis::serializeStateChangeTime()
 {
-    fs::path path{CHASSIS_STATE_CHANGE_PERSIST_PATH};
+    fs::path path{fmt::format(CHASSIS_STATE_CHANGE_PERSIST_PATH, id)};
     std::ofstream os(path.c_str(), std::ios::binary);
     cereal::JSONOutputArchive oarchive(os);
 
@@ -682,7 +684,7 @@
 
 bool Chassis::deserializeStateChangeTime(uint64_t& time, PowerState& state)
 {
-    fs::path path{CHASSIS_STATE_CHANGE_PERSIST_PATH};
+    fs::path path{fmt::format(CHASSIS_STATE_CHANGE_PERSIST_PATH, id)};
 
     try
     {
diff --git a/chassis_state_manager.hpp b/chassis_state_manager.hpp
index 3bd44cd..e82a4cd 100644
--- a/chassis_state_manager.hpp
+++ b/chassis_state_manager.hpp
@@ -176,23 +176,18 @@
 
     /** @brief Serialize and persist requested POH counter.
      *
-     *  @param[in] dir - pathname of file where the serialized POH counter will
-     *                   be placed.
-     *
      *  @return fs::path - pathname of persisted requested POH counter.
      */
-    fs::path
-        serializePOH(const fs::path& dir = fs::path(POH_COUNTER_PERSIST_PATH));
+    fs::path serializePOH();
 
     /** @brief Deserialize a persisted requested POH counter.
      *
-     *  @param[in] path - pathname of persisted POH counter file
      *  @param[in] retCounter - deserialized POH counter value
      *
      *  @return bool - true if the deserialization was successful, false
      *                 otherwise.
      */
-    bool deserializePOH(const fs::path& path, uint32_t& retCounter);
+    bool deserializePOH(uint32_t& retCounter);
 
     /** @brief Sets the LastStateChangeTime property and persists it. */
     void setStateChangeTime();
diff --git a/chassis_state_manager_main.cpp b/chassis_state_manager_main.cpp
index eac4fd4..c1dccf7 100644
--- a/chassis_state_manager_main.cpp
+++ b/chassis_state_manager_main.cpp
@@ -2,14 +2,21 @@
 
 #include "chassis_state_manager.hpp"
 
+#include <fmt/format.h>
 #include <getopt.h>
 
 #include <sdbusplus/bus.hpp>
 
 #include <cstdlib>
 #include <exception>
+#include <filesystem>
 #include <iostream>
 
+constexpr auto LEGACY_POH_COUNTER_PERSIST_PATH =
+    "/var/lib/phosphor-state-manager/POHCounter";
+constexpr auto LEGACY_STATE_CHANGE_PERSIST_PATH =
+    "/var/lib/phosphor-state-manager/chassisStateChangeTime";
+
 int main(int argc, char** argv)
 {
     size_t chassisId = 0;
@@ -30,12 +37,37 @@
         }
     }
 
+    namespace fs = std::filesystem;
+
     auto bus = sdbusplus::bus::new_default();
 
     auto chassisBusName =
         std::string{CHASSIS_BUSNAME} + std::to_string(chassisId);
     auto objPathInst = std::string{CHASSIS_OBJPATH} + std::to_string(chassisId);
 
+    if (chassisId == 0)
+    {
+        // Chassis State Manager was only support single-chassis and there only
+        // two file to store persist values(POH and state change time), to
+        // support multi-chassis state mamagement, each service access new file
+        // paths with prefix 'chassisN', if any legacy persist file is exist,
+        // rename it to the new file format of chassis0.
+
+        fs::path legacyPohPath{LEGACY_POH_COUNTER_PERSIST_PATH};
+        fs::path legacyStateChangePath{LEGACY_STATE_CHANGE_PERSIST_PATH};
+        fs::path newPohPath{fmt::format(POH_COUNTER_PERSIST_PATH, chassisId)};
+        fs::path newStateChangePath{
+            fmt::format(CHASSIS_STATE_CHANGE_PERSIST_PATH, chassisId)};
+        if (fs::exists(legacyPohPath))
+        {
+            fs::rename(legacyPohPath, newPohPath);
+        }
+        if (fs::exists(legacyStateChangePath))
+        {
+            fs::rename(legacyStateChangePath, newStateChangePath);
+        }
+    }
+
     // Add sdbusplus ObjectManager.
     sdbusplus::server::manager::manager objManager(bus, objPathInst.c_str());
     phosphor::state::manager::Chassis manager(bus, objPathInst.c_str(),
diff --git a/host_state_manager.cpp b/host_state_manager.cpp
index 78899a0..9639a4b 100644
--- a/host_state_manager.cpp
+++ b/host_state_manager.cpp
@@ -92,7 +92,7 @@
         server::Host::requestedHostTransition(Transition::Off);
     }
 
-    if (!deserialize(HOST_STATE_PERSIST_PATH))
+    if (!deserialize())
     {
         // set to default value.
         server::Host::requestedHostTransition(Transition::Off);
@@ -361,16 +361,18 @@
     return rebootCount;
 }
 
-fs::path Host::serialize(const fs::path& dir)
+fs::path Host::serialize()
 {
-    std::ofstream os(dir.c_str(), std::ios::binary);
+    fs::path path{fmt::format(HOST_STATE_PERSIST_PATH, id)};
+    std::ofstream os(path.c_str(), std::ios::binary);
     cereal::JSONOutputArchive oarchive(os);
     oarchive(*this);
-    return dir;
+    return path;
 }
 
-bool Host::deserialize(const fs::path& path)
+bool Host::deserialize()
 {
+    fs::path path{fmt::format(HOST_STATE_PERSIST_PATH, id)};
     try
     {
         if (fs::exists(path))
@@ -406,6 +408,7 @@
     executeTransition(value);
 
     auto retVal = server::Host::requestedHostTransition(value);
+
     serialize();
     return retVal;
 }
diff --git a/host_state_manager.hpp b/host_state_manager.hpp
index 6b9d687..3e0763e 100644
--- a/host_state_manager.hpp
+++ b/host_state_manager.hpp
@@ -260,21 +260,16 @@
 
     /** @brief Serialize and persist requested host state
      *
-     *  @param[in] dir - pathname of file where the serialized host state will
-     *                   be placed.
-     *
      *  @return fs::path - pathname of persisted requested host state.
      */
-    fs::path serialize(const fs::path& dir = fs::path(HOST_STATE_PERSIST_PATH));
+    fs::path serialize();
 
     /** @brief Deserialze a persisted requested host state.
      *
-     *  @param[in] path - pathname of persisted host state file
-     *
      *  @return bool - true if the deserialization was successful, false
      *                 otherwise.
      */
-    bool deserialize(const fs::path& path);
+    bool deserialize();
 
     /**
      * @brief Get target name of a HostState
diff --git a/host_state_manager_main.cpp b/host_state_manager_main.cpp
index b96cdbf..13c8f53 100644
--- a/host_state_manager_main.cpp
+++ b/host_state_manager_main.cpp
@@ -2,6 +2,7 @@
 
 #include "host_state_manager.hpp"
 
+#include <fmt/format.h>
 #include <getopt.h>
 
 #include <sdbusplus/bus.hpp>
@@ -11,6 +12,9 @@
 #include <filesystem>
 #include <iostream>
 
+constexpr auto LEGACY_HOST_STATE_PERSIST_PATH =
+    "/var/lib/phosphor-state-manager/requestedHostTransition";
+
 int main(int argc, char** argv)
 {
     size_t hostId = 0;
@@ -40,6 +44,22 @@
     auto hostBusName = std::string{HOST_BUSNAME} + std::to_string(hostId);
     auto objPathInst = std::string{HOST_OBJPATH} + std::to_string(hostId);
 
+    if (hostId == 0)
+    {
+        // Host State Manager was only support single-host and there only one
+        // file to store persist values, to support multi-host state management,
+        // each service instance access new file path format with prefix 'hostN'
+        // now.For backward compatibility if there is a legacy persist file
+        // exist, rename it to the new file format of host0.
+
+        fs::path legacyPath{LEGACY_HOST_STATE_PERSIST_PATH};
+        fs::path newPath{fmt::format(HOST_STATE_PERSIST_PATH, hostId)};
+        if (fs::exists(legacyPath))
+        {
+            fs::rename(legacyPath, newPath);
+        }
+    }
+
     // Add sdbusplus ObjectManager.
     sdbusplus::server::manager::manager objManager(bus, objPathInst.c_str());
 
diff --git a/meson_options.txt b/meson_options.txt
index 8592d1d..f042b64 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -50,20 +50,20 @@
 
 option(
     'host-state-persist-path', type: 'string',
-    value: '/var/lib/phosphor-state-manager/requestedHostTransition',
-    description: 'Path of file for storing requested host state.',
+    value: '/var/lib/phosphor-state-manager/host{}-PersistData',
+    description: 'Path format of file for storing requested HostState,boot progress and os status.',
 )
 
 option(
     'poh-counter-persist-path', type: 'string',
-    value: '/var/lib/phosphor-state-manager/POHCounter',
-    description: 'Path of file for storing POH counter.',
+    value: '/var/lib/phosphor-state-manager/chassis{}-POHCounter',
+    description: 'Path format of file for storing POH counter.',
 )
 
 option(
     'chassis-state-change-persist-path', type: 'string',
-    value: '/var/lib/phosphor-state-manager/chassisStateChangeTime',
-    description: 'Path of file for storing the state change time.',
+    value: '/var/lib/phosphor-state-manager/chassis{}-StateChangeTime',
+    description: 'Path format of file for storing the state change time.',
 )
 
 option(