Persistent state of zone 69/36269/1
authorPiotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
Mon, 2 Mar 2015 10:57:50 +0000 (11:57 +0100)
committerPiotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
Wed, 4 Mar 2015 10:31:38 +0000 (11:31 +0100)
[Bug/Feature]   Zone was always started after vasum restart regardless
                of the zone state before restart
[Cause]         N/A
[Solution]      N/A
[Verification]  Run tests. Run vasum, pause one container, restart
                vasum, check this container is still paused. The same
                test with stopped and started state.

Change-Id: I0426e3e4f2af9b2bc0c110a7702b9c742a2747e6

23 files changed:
server/configs/templates/default.conf
server/server.cpp
server/zone-config.hpp
server/zone.cpp
server/zone.hpp
server/zones-manager.cpp
server/zones-manager.hpp
tests/unit_tests/client/configs/ut-client/templates/console-dbus.conf.in
tests/unit_tests/client/ut-client.cpp
tests/unit_tests/server/configs/ut-server/templates/default.conf
tests/unit_tests/server/configs/ut-zone-admin/templates/buggy.conf
tests/unit_tests/server/configs/ut-zone-admin/templates/missing.conf
tests/unit_tests/server/configs/ut-zone-admin/templates/test-no-shutdown.conf
tests/unit_tests/server/configs/ut-zone-admin/templates/test.conf
tests/unit_tests/server/configs/ut-zone/templates/buggy.conf
tests/unit_tests/server/configs/ut-zone/templates/test-dbus.conf.in
tests/unit_tests/server/configs/ut-zone/templates/test.conf
tests/unit_tests/server/configs/ut-zones-manager/templates/console-dbus.conf.in
tests/unit_tests/server/configs/ut-zones-manager/templates/console.conf
tests/unit_tests/server/ut-server.cpp
tests/unit_tests/server/ut-zone-admin.cpp
tests/unit_tests/server/ut-zone.cpp
tests/unit_tests/server/ut-zones-manager.cpp

index 2aa7a66..9eb0e08 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "tizen-common-wayland.sh",
     "initWithArgs" : [],
+    "requestedState" : "stopped",
     "ipv4Gateway" : "10.0.~IP~.1",
     "ipv4" : "10.0.~IP~.2",
     "cpuQuotaForeground" : -1,
index b4e2344..c2ca778 100644 (file)
@@ -107,7 +107,7 @@ void Server::run(bool asRoot)
         utils::ScopedGlibLoop loop;
         ZonesManager manager(mConfigPath);
 
-        manager.startAll();
+        manager.restoreAll();
         LOGI("Daemon started");
 
         gSignalLatch.wait();
@@ -118,7 +118,7 @@ void Server::run(bool asRoot)
         }
 
         LOGI("Stopping daemon...");
-        // manager.stopAll() will be called in destructor
+        // manager.shutdownAll() will be called in destructor
     }
     LOGI("Daemon stopped");
 }
index da4b570..f5d81e5 100644 (file)
@@ -110,6 +110,11 @@ struct ZoneConfig {
 struct ZoneDynamicConfig {
 
     /**
+     * Requested zone state after restore
+     */
+    std::string requestedState;
+
+    /**
      * IP v4 gateway address
      */
     std::string ipv4Gateway;
@@ -131,6 +136,7 @@ struct ZoneDynamicConfig {
 
     CONFIG_REGISTER
     (
+        requestedState,
         ipv4Gateway,
         ipv4,
         vt,
index fed66fa..1bc2d09 100644 (file)
@@ -50,6 +50,10 @@ typedef std::lock_guard<std::recursive_mutex> Lock;
 const int RECONNECT_RETRIES = 15;
 const int RECONNECT_DELAY = 1 * 1000;
 
+const std::string STATE_STOPPED = "stopped";
+const std::string STATE_RUNNING = "running";
+const std::string STATE_PAUSED = "paused";
+
 } // namespace
 
 Zone::Zone(const utils::Worker::Pointer& worker,
@@ -60,6 +64,7 @@ Zone::Zone(const utils::Worker::Pointer& worker,
            const std::string& lxcTemplatePrefix,
            const std::string& baseRunMountPointPath)
     : mWorker(worker)
+    , mDbPath(dbPath)
 {
     const std::string dbPrefix = getZoneDbPrefix(zoneId);
     config::loadFromKVStoreWithJsonFile(dbPath, zoneTemplatePath, mConfig, dbPrefix);
@@ -118,9 +123,46 @@ int Zone::getPrivilege() const
     return mConfig.privilege;
 }
 
+void Zone::saveDynamicConfig()
+{
+    config::saveToKVStore(mDbPath, mDynamicConfig, getZoneDbPrefix(getId()));
+}
+
+void Zone::updateRequestedState(const std::string& state)
+{
+    // assume mutex is locked
+    if (state != mDynamicConfig.requestedState) {
+        LOGT("Set requested state of " << getId() << " to " << state);
+        mDynamicConfig.requestedState = state;
+        saveDynamicConfig();
+    }
+}
+
+void Zone::restore()
+{
+    std::string requestedState;
+    {
+        Lock lock(mReconnectMutex);
+        requestedState = mDynamicConfig.requestedState;
+        LOGT("Requested state of " << getId() << ": " << requestedState);
+    }
+
+    if (requestedState == STATE_RUNNING) {
+        start();
+    } else if (requestedState == STATE_STOPPED) {
+    } else if (requestedState == STATE_PAUSED) {
+        start();
+        suspend();
+    } else {
+        LOGE("Invalid requested state: " << requestedState);
+        assert(0 && "invalid requested state");
+    }
+}
+
 void Zone::start()
 {
     Lock lock(mReconnectMutex);
+    updateRequestedState(STATE_RUNNING);
     mProvision->start();
     if (mConfig.enableDbusIntegration) {
         mConnectionTransport.reset(new ZoneConnectionTransport(mRunMountPoint));
@@ -135,9 +177,12 @@ void Zone::start()
     // refocus in ZonesManager will adjust cpu quota after all
 }
 
-void Zone::stop()
+void Zone::stop(bool saveState)
 {
     Lock lock(mReconnectMutex);
+    if (saveState) {
+        updateRequestedState(STATE_STOPPED);
+    }
     if (mAdmin->isRunning()) {
         // boost stopping
         goForeground();
@@ -192,6 +237,7 @@ std::string Zone::getDbusAddress() const
 
 int Zone::getVT() const
 {
+    Lock lock(mReconnectMutex);
     return mDynamicConfig.vt;
 }
 
@@ -275,12 +321,14 @@ void Zone::suspend()
 {
     Lock lock(mReconnectMutex);
     mAdmin->suspend();
+    updateRequestedState(STATE_PAUSED);
 }
 
 void Zone::resume()
 {
     Lock lock(mReconnectMutex);
     mAdmin->resume();
+    updateRequestedState(STATE_RUNNING);
 }
 
 bool Zone::isPaused()
@@ -329,7 +377,7 @@ void Zone::reconnectHandler()
     }
 
     LOGE(getId() << ": Reconnecting to the DBUS has failed, stopping the zone");
-    stop();
+    stop(false);
 }
 
 void Zone::setNotifyActiveZoneCallback(const NotifyActiveZoneCallback& callback)
index 832fcec..69d0324 100644 (file)
@@ -98,14 +98,20 @@ public:
     int getPrivilege() const;
 
     /**
+     * Restore zone to the previous state
+     */
+    void restore();
+
+    /**
      * Boot the zone to the background.
      */
     void start();
 
     /**
      * Try to shutdown the zone, if failed, destroy it.
+     * @param saveState save zone's state
      */
-    void stop();
+    void stop(bool saveState);
 
     /**
      * Activate this zone's VT
@@ -319,11 +325,14 @@ private:
     std::string mDbusAddress;
     std::string mRunMountPoint;
     std::string mRootPath;
+    std::string mDbPath;
 
     void onNameLostCallback();
     void reconnectHandler();
     void connect();
     void disconnect();
+    void saveDynamicConfig();
+    void updateRequestedState(const std::string& state);
 };
 
 
index 283f57f..d90bab7 100644 (file)
@@ -226,9 +226,9 @@ ZonesManager::~ZonesManager()
 
     if (!mDetachOnExit) {
         try {
-            stopAll();
+            shutdownAll();
         } catch (ServerException&) {
-            LOGE("Failed to stop all of the zones");
+            LOGE("Failed to shutdown all of the zones");
         }
     }
     // wait for all tasks to complete
@@ -434,27 +434,27 @@ void ZonesManager::refocus()
     focusInternal(iter);
 }
 
-void ZonesManager::startAll()
+void ZonesManager::restoreAll()
 {
-    LOGI("Starting all zones");
+    LOGI("Restoring all zones");
 
     Lock lock(mMutex);
 
     for (auto& zone : mZones) {
-        zone->start();
+        zone->restore();
     }
 
     refocus();
 }
 
-void ZonesManager::stopAll()
+void ZonesManager::shutdownAll()
 {
     LOGI("Stopping all zones");
 
     Lock lock(mMutex);
 
     for (auto& zone : mZones) {
-        zone->stop();
+        zone->stop(false);
     }
 
     refocus();
@@ -463,26 +463,19 @@ void ZonesManager::stopAll()
 bool ZonesManager::isPaused(const std::string& zoneId)
 {
     Lock lock(mMutex);
-
-    auto iter = findZone(zoneId);
-    if (iter == mZones.end()) {
-        LOGE("No such zone id: " << zoneId);
-        throw InvalidZoneIdException("No such zone");
-    }
-
-    return get(iter).isPaused();
+    return getZone(zoneId).isPaused();
 }
 
 bool ZonesManager::isRunning(const std::string& zoneId)
 {
     Lock lock(mMutex);
+    return getZone(zoneId).isRunning();
+}
 
-    auto iter = findZone(zoneId);
-    if (iter == mZones.end()) {
-        LOGE("No such zone id: " << zoneId);
-        throw InvalidZoneIdException("No such zone");
-    }
-    return get(iter).isRunning();
+bool ZonesManager::isStopped(const std::string& zoneId)
+{
+    Lock lock(mMutex);
+    return getZone(zoneId).isStopped();
 }
 
 std::string ZonesManager::getRunningForegroundZoneId()
@@ -1265,7 +1258,7 @@ void ZonesManager::handleShutdownZoneCall(const std::string& id,
                 result->setError(api::ERROR_INVALID_ID, "No such zone id");
                 return;
             }
-            get(iter).stop();
+            get(iter).stop(true);
             refocus();
             result->setVoid();
         } catch (ZoneOperationException& e) {
index ee1606d..cb730e3 100644 (file)
@@ -70,14 +70,14 @@ public:
     void focus(const std::string& zoneId);
 
     /**
-     * Start up all the configured zones
+     * Restore all the configured zones to the saved state
      */
-    void startAll();
+    void restoreAll();
 
     /**
-     * Stop all managed zones
+     * Shutdown all managed zones without changing the saved state
      */
-    void stopAll();
+    void shutdownAll();
 
     /**
      * @return Is the zone in a paused state?
@@ -90,6 +90,11 @@ public:
     bool isRunning(const std::string& zoneId);
 
     /**
+     * @return Is the zone stopped?
+     */
+    bool isStopped(const std::string& zoneId);
+
+    /**
      * @return id of the currently focused/foreground zone
      */
     std::string getRunningForegroundZoneId();
index 0bd0e03..7778208 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal-dbus.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; /usr/bin/dbus-daemon --config-file=@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/ut-dbus.conf --fork; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 20,
index 1c55668..ce31795 100644 (file)
@@ -77,7 +77,7 @@ struct Fixture {
         cm.createZone("zone1", TEMPLATE_NAME);
         cm.createZone("zone2", TEMPLATE_NAME);
         cm.createZone("zone3", TEMPLATE_NAME);
-        cm.startAll();
+        cm.restoreAll();
         LOGI("------- setup complete --------");
     }
 
@@ -153,7 +153,7 @@ BOOST_FIXTURE_TEST_SUITE(ClientSuite, Fixture)
 
 BOOST_AUTO_TEST_CASE(NotRunningServerTest)
 {
-    cm.stopAll();
+    cm.shutdownAll();
 
     VsmClient client = vsm_client_create();
     VsmStatus status = vsm_connect_custom(client,
index 875cdc4..a2f703e 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 20,
index 07569fe..f585ae8 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal.sh",
     "initWithArgs" : ["/foo"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 10,
index e0b5e4a..a3f305b 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "missing.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 10,
index 1579851..98e95ab 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal.sh",
     "initWithArgs" : ["/bin/sh"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 10,
index d74f221..a16b3fa 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 10,
index 1b449bc..79436c0 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "/buggy/path",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 10,
index 9e9a1f8..5d76429 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal-dbus.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; /usr/bin/dbus-daemon --config-file=@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zone/ut-dbus.conf --fork; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 10,
index 3bc3277..168aa21 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 10,
index 0bd0e03..7778208 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal-dbus.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; /usr/bin/dbus-daemon --config-file=@VSM_TEST_CONFIG_INSTALL_DIR@/server/ut-zones-manager/ut-dbus.conf --fork; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 20,
index 9b3013c..6e49c5b 100644 (file)
@@ -1,6 +1,7 @@
 {
     "lxcTemplate" : "minimal.sh",
     "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; read"],
+    "requestedState" : "running",
     "ipv4Gateway" : "",
     "ipv4" : "",
     "privilege" : 20,
index 4df5d89..eccea8a 100644 (file)
@@ -63,7 +63,7 @@ struct Fixture {
         vasum::ZonesManager manager(TEST_CONFIG_PATH);
         manager.createZone("zone1", TEMPLATE_NAME);
         manager.createZone("zone2", TEMPLATE_NAME);
-        manager.startAll();
+        manager.restoreAll();
     }
 };
 } // namespace
index 4dd08db..c711169 100644 (file)
@@ -158,10 +158,10 @@ BOOST_AUTO_TEST_CASE(SuspendResumeTest)
 
 BOOST_AUTO_TEST_CASE(SchedulerLevelTest)
 {
-    BOOST_REQUIRE(mConfig.cpuQuotaForeground != mConfig.cpuQuotaBackground);
-
     auto admin = create(TEST_CONFIG_PATH);
 
+    BOOST_REQUIRE(mConfig.cpuQuotaForeground != mConfig.cpuQuotaBackground);
+
     admin->start();
     ensureStarted();
 
index 3cd6031..37f65be 100644 (file)
@@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE(StartStopTest)
     auto c = create(TEST_CONFIG_PATH);
     c->start();
     ensureStarted();
-    c->stop();
+    c->stop(true);
 }
 
 BOOST_AUTO_TEST_CASE(DbusConnectionTest)
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(DbusConnectionTest)
     auto c = create(TEST_DBUS_CONFIG_PATH);
     c->start();
     ensureStarted();
-    c->stop();
+    c->stop(true);
 }
 
 // TODO: DbusReconnectionTest
index e93ab84..0e40093 100644 (file)
@@ -508,9 +508,9 @@ BOOST_AUTO_TEST_CASE(StartStopTest)
     cm.createZone("zone1", SIMPLE_TEMPLATE);
     cm.createZone("zone2", SIMPLE_TEMPLATE);
 
-    cm.startAll();
+    cm.restoreAll();
     BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), "zone1");
-    cm.stopAll();
+    cm.shutdownAll();
     BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), "");
 }
 
@@ -520,13 +520,13 @@ BOOST_AUTO_TEST_CASE(DetachOnExitTest)
         ZonesManager cm(TEST_CONFIG_PATH);
         cm.createZone("zone1", SIMPLE_TEMPLATE);
         cm.createZone("zone2", SIMPLE_TEMPLATE);
-        cm.startAll();
+        cm.restoreAll();
         BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), "zone1");
         cm.setZonesDetachOnExit();
     }
     {
         ZonesManager cm(TEST_CONFIG_PATH);
-        cm.startAll();
+        cm.restoreAll();
         BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), "zone1");
     }
 }
@@ -537,7 +537,7 @@ BOOST_AUTO_TEST_CASE(FocusTest)
     cm.createZone("zone1", SIMPLE_TEMPLATE);
     cm.createZone("zone2", SIMPLE_TEMPLATE);
     cm.createZone("zone3", SIMPLE_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     BOOST_CHECK(cm.getRunningForegroundZoneId() == "zone1");
     cm.focus("zone2");
@@ -554,7 +554,7 @@ BOOST_AUTO_TEST_CASE(NotifyActiveZoneTest)
     cm.createZone("zone1", DBUS_TEMPLATE);
     cm.createZone("zone2", DBUS_TEMPLATE);
     cm.createZone("zone3", DBUS_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     Latch signalReceivedLatch;
     std::map<int, std::vector<std::string>> signalReceivedSourcesMap;
@@ -624,7 +624,7 @@ BOOST_AUTO_TEST_CASE(DisplayOffTest)
     cm.createZone("zone1", DBUS_TEMPLATE);
     cm.createZone("zone2", DBUS_TEMPLATE);
     cm.createZone("zone3", DBUS_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     std::vector<std::unique_ptr<DbusAccessory>> clients;
     for (int i = 1; i <= TEST_DBUS_CONNECTION_ZONES_COUNT; ++i) {
@@ -661,7 +661,7 @@ BOOST_AUTO_TEST_CASE(MoveFileTest)
     cm.createZone("zone1", DBUS_TEMPLATE);
     cm.createZone("zone2", DBUS_TEMPLATE);
     cm.createZone("zone3", DBUS_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     Latch notificationLatch;
     std::string notificationSource;
@@ -763,7 +763,7 @@ BOOST_AUTO_TEST_CASE(AllowSwitchToDefaultTest)
     cm.createZone("zone1", DBUS_TEMPLATE);
     cm.createZone("zone2", DBUS_TEMPLATE);
     cm.createZone("zone3", DBUS_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     std::vector<std::unique_ptr<DbusAccessory>> clients;
     for (int i = 1; i <= TEST_DBUS_CONNECTION_ZONES_COUNT; ++i) {
@@ -812,7 +812,7 @@ BOOST_AUTO_TEST_CASE(ProxyCallTest)
     cm.createZone("zone1", DBUS_TEMPLATE);
     cm.createZone("zone2", DBUS_TEMPLATE);
     cm.createZone("zone3", DBUS_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     std::map<int, std::unique_ptr<DbusAccessory>> dbuses;
     for (int i = 0; i <= TEST_DBUS_CONNECTION_ZONES_COUNT; ++i) {
@@ -904,9 +904,9 @@ BOOST_AUTO_TEST_CASE(GetZoneDbusesTest)
     cm.createZone("zone3", DBUS_TEMPLATE);
 
     BOOST_CHECK(EXPECTED_DBUSES_NONE == host.callMethodGetZoneDbuses());
-    cm.startAll();
+    cm.restoreAll();
     BOOST_CHECK(EXPECTED_DBUSES_ALL == host.callMethodGetZoneDbuses());
-    cm.stopAll();
+    cm.shutdownAll();
     BOOST_CHECK(EXPECTED_DBUSES_NONE == host.callMethodGetZoneDbuses());
 }
 
@@ -919,9 +919,9 @@ BOOST_AUTO_TEST_CASE(GetZoneDbusesNoDbusTest)
     cm.createZone("zone3", SIMPLE_TEMPLATE);
 
     BOOST_CHECK(EXPECTED_DBUSES_NONE == host.callMethodGetZoneDbuses());
-    cm.startAll();
+    cm.restoreAll();
     BOOST_CHECK(EXPECTED_DBUSES_NONE == host.callMethodGetZoneDbuses());
-    cm.stopAll();
+    cm.shutdownAll();
     BOOST_CHECK(EXPECTED_DBUSES_NONE == host.callMethodGetZoneDbuses());
 }
 
@@ -961,7 +961,7 @@ BOOST_AUTO_TEST_CASE(ZoneDbusesSignalsTest)
         BOOST_CHECK(signalLatch.empty());
         BOOST_CHECK(collectedDbuses.empty());
 
-        cm.startAll();
+        cm.restoreAll();
 
         BOOST_REQUIRE(signalLatch.waitForN(TEST_DBUS_CONNECTION_ZONES_COUNT, EVENT_TIMEOUT));
         BOOST_CHECK(signalLatch.empty());
@@ -998,7 +998,7 @@ BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest)
     cm.createZone("zone1", SIMPLE_TEMPLATE);
     cm.createZone("zone2", SIMPLE_TEMPLATE);
     cm.createZone("zone3", SIMPLE_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     DbusAccessory dbus(DbusAccessory::HOST_ID);
 
@@ -1011,7 +1011,7 @@ BOOST_AUTO_TEST_CASE(GetActiveZoneIdTest)
         BOOST_CHECK(dbus.callMethodGetActiveZoneId() == zoneId);
     }
 
-    cm.stopAll();
+    cm.shutdownAll();
     BOOST_CHECK(dbus.callMethodGetActiveZoneId() == "");
 }
 
@@ -1021,7 +1021,7 @@ BOOST_AUTO_TEST_CASE(SetActiveZoneTest)
     cm.createZone("zone1", SIMPLE_TEMPLATE);
     cm.createZone("zone2", SIMPLE_TEMPLATE);
     cm.createZone("zone3", SIMPLE_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     DbusAccessory dbus(DbusAccessory::HOST_ID);
 
@@ -1038,7 +1038,7 @@ BOOST_AUTO_TEST_CASE(SetActiveZoneTest)
                             DbusException,
                             WhatEquals("No such zone id"));
 
-    cm.stopAll();
+    cm.shutdownAll();
     BOOST_REQUIRE_EXCEPTION(dbus.callMethodSetActiveZone("zone1"),
                             DbusException,
                             WhatEquals("Could not activate stopped or paused zone"));
@@ -1051,7 +1051,7 @@ BOOST_AUTO_TEST_CASE(CreateDestroyZoneTest)
     const std::string zone3 = "test3";
 
     ZonesManager cm(TEST_CONFIG_PATH);
-    cm.startAll();
+    cm.restoreAll();
 
     BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), "");
 
@@ -1074,7 +1074,7 @@ BOOST_AUTO_TEST_CASE(CreateDestroyZoneTest)
     dbus.callAsyncMethodCreateZone(zone3, SIMPLE_TEMPLATE, resultCallback);
     BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
 
-    cm.startAll();
+    cm.restoreAll();
 
     BOOST_CHECK_EQUAL(cm.getRunningForegroundZoneId(), zone1);
     cm.focus(zone3);
@@ -1107,7 +1107,7 @@ BOOST_AUTO_TEST_CASE(CreateDestroyZonePersistenceTest)
 
     auto getZoneIds = []() -> std::vector<std::string> {
         ZonesManager cm(TEST_CONFIG_PATH);
-        cm.startAll();
+        cm.restoreAll();
 
         DbusAccessory dbus(DbusAccessory::HOST_ID);
         return dbus.callMethodGetZoneIds();
@@ -1140,6 +1140,77 @@ BOOST_AUTO_TEST_CASE(CreateDestroyZonePersistenceTest)
     BOOST_CHECK(getZoneIds().empty());
 }
 
+BOOST_AUTO_TEST_CASE(ZoneStatePersistenceTest)
+{
+    const std::string zone1 = "zone1";
+    const std::string zone2 = "zone2";
+    const std::string zone3 = "zone3";
+    const std::string zone4 = "zone4";
+    const std::string zone5 = "zone5";
+
+    Latch callDone;
+    auto resultCallback = [&]() {
+        callDone.set();
+    };
+
+    // firts run
+    {
+        ZonesManager cm(TEST_CONFIG_PATH);
+        DbusAccessory dbus(DbusAccessory::HOST_ID);
+
+        // zone1 - created
+        dbus.callAsyncMethodCreateZone(zone1, SIMPLE_TEMPLATE, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+
+        // zone2 - started
+        dbus.callAsyncMethodCreateZone(zone2, SIMPLE_TEMPLATE, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callAsyncMethodStartZone(zone2, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        BOOST_CHECK(cm.isRunning(zone2));
+
+        // zone3 - started then paused
+        dbus.callAsyncMethodCreateZone(zone3, SIMPLE_TEMPLATE, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callAsyncMethodStartZone(zone3, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callMethodLockZone(zone3);
+        BOOST_CHECK(cm.isPaused(zone3));
+
+        // zone4 - started then stopped
+        dbus.callAsyncMethodCreateZone(zone4, SIMPLE_TEMPLATE, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callAsyncMethodStartZone(zone4, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callAsyncMethodShutdownZone(zone4, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        BOOST_CHECK(cm.isStopped(zone4));
+
+        // zone5 - started then stopped then started
+        dbus.callAsyncMethodCreateZone(zone5, SIMPLE_TEMPLATE, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callAsyncMethodStartZone(zone5, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callAsyncMethodShutdownZone(zone5, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        dbus.callAsyncMethodStartZone(zone5, resultCallback);
+        BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+        BOOST_CHECK(cm.isRunning(zone5));
+    }
+
+    // second run
+    {
+        ZonesManager cm(TEST_CONFIG_PATH);
+        cm.restoreAll();
+
+        BOOST_CHECK(cm.isRunning(zone1)); // because the default json value
+        BOOST_CHECK(cm.isRunning(zone2));
+        BOOST_CHECK(cm.isPaused(zone3));
+        BOOST_CHECK(cm.isStopped(zone4));
+        BOOST_CHECK(cm.isRunning(zone5));
+    }
+}
+
 BOOST_AUTO_TEST_CASE(StartShutdownZoneTest)
 {
     const std::string zone1 = "zone1";
@@ -1186,7 +1257,7 @@ BOOST_AUTO_TEST_CASE(LockUnlockZoneTest)
     cm.createZone("zone1", DBUS_TEMPLATE);
     cm.createZone("zone2", DBUS_TEMPLATE);
     cm.createZone("zone3", DBUS_TEMPLATE);
-    cm.startAll();
+    cm.restoreAll();
 
     DbusAccessory dbus(DbusAccessory::HOST_ID);
 
@@ -1208,7 +1279,7 @@ BOOST_AUTO_TEST_CASE(LockUnlockZoneTest)
                             DbusException,
                             WhatEquals("No such zone id"));
 
-    cm.stopAll();
+    cm.shutdownAll();
     BOOST_REQUIRE_EXCEPTION(dbus.callMethodLockZone("zone1"),
                             DbusException,
                             WhatEquals("Zone is not running"));