diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 835cc5d..1fd5df7 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -23,6 +23,7 @@
 #include "../lib/redfish_sessions.hpp"
 #include "../lib/roles.hpp"
 #include "../lib/service_root.hpp"
+#include "../lib/systems.hpp"
 #include "../lib/thermal.hpp"
 #include "../lib/update_service.hpp"
 #include "webserver_common.hpp"
@@ -57,6 +58,10 @@
     nodes.emplace_back(std::make_unique<UpdateService>(app));
     nodes.emplace_back(std::make_unique<SoftwareInventoryCollection>(app));
     nodes.emplace_back(std::make_unique<SoftwareInventory>(app));
+    nodes.emplace_back(std::make_unique<VlanNetworkInterfaceCollection>(app));
+    nodes.emplace_back(std::make_unique<SystemsCollection>(app));
+    nodes.emplace_back(std::make_unique<Systems>(app));
+
     for (auto& node : nodes) {
       node->getSubRoutes(nodes);
     }
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index 6047f3e..95f4634 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -27,7 +27,7 @@
 // Note, this is not a very useful variant, but because it isn't used to get
 // values, it should be as simple as possible
 // TODO(ed) invent a nullvariant type
-using VariantType = sdbusplus::message::variant<std::string>;
+using VariantType = sdbusplus::message::variant<bool, std::string>;
 using ManagedObjectsType = std::vector<std::pair<
     sdbusplus::message::object_path,
     std::vector<std::pair<std::string,
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
new file mode 100644
index 0000000..7619f14
--- /dev/null
+++ b/redfish-core/lib/systems.hpp
@@ -0,0 +1,685 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#pragma once
+
+#include <error_messages.hpp>
+#include <utils/json_utils.hpp>
+#include "node.hpp"
+#include "boost/container/flat_map.hpp"
+
+namespace redfish {
+
+/**
+ * SystemAsyncResp
+ * Gathers data needed for response processing after async calls are done
+ */
+class SystemAsyncResp {
+ public:
+  SystemAsyncResp(crow::response &response) : res(response) {}
+
+  ~SystemAsyncResp() {
+    if (res.result() != (boost::beast::http::status::ok)) {
+      // Reset the json object to clear out any data that made it in before the
+      // error happened
+      // todo(ed) handle error condition with proper code
+      res.json_value = messages::internalError();
+    }
+    res.end();
+  }
+
+  void setErrorStatus() {
+    res.result(boost::beast::http::status::internal_server_error);
+  }
+
+  crow::response &res;
+};
+
+/**
+ * OnDemandSystemsProvider
+ * Board provider class that retrieves data directly from dbus, before seting
+ * it into JSON output. This does not cache any data.
+ *
+ * Class can be a good example on how to scale different data providing
+ * solutions to produce single schema output.
+ *
+ * TODO(Pawel)
+ * This perhaps shall be different file, which has to be chosen on compile time
+ * depending on OEM needs
+ */
+class OnDemandSystemsProvider {
+ public:
+  template <typename CallbackFunc>
+  void getBaseboardList(CallbackFunc &&callback) {
+    CROW_LOG_DEBUG << "Get list of available boards.";
+    crow::connections::system_bus->async_method_call(
+        [callback{std::move(callback)}](const boost::system::error_code ec,
+                                        const std::vector<std::string> &resp) {
+          // Callback requires vector<string> to retrieve all available board
+          // list.
+          std::vector<std::string> board_list;
+          if (ec) {
+            // Something wrong on DBus, the error_code is not important at this
+            // moment, just return success=false, and empty output. Since size
+            // of vector may vary depending on information from Entity Manager,
+            // and empty output could not be treated same way as error.
+            callback(false, board_list);
+            return;
+          }
+          CROW_LOG_DEBUG << "Got " << resp.size() << " boards.";
+          // Iterate over all retrieved ObjectPaths.
+          for (const std::string &objpath : resp) {
+            std::size_t last_pos = objpath.rfind("/");
+            if (last_pos != std::string::npos) {
+              board_list.emplace_back(objpath.substr(last_pos + 1));
+            }
+          }
+          // Finally make a callback with useful data
+          callback(true, board_list);
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+        "/xyz/openbmc_project/inventory", int32_t(0),
+        std::array<const char *, 1>{
+            "xyz.openbmc_project.Inventory.Item.Board"});
+  };
+
+  /**
+   * @brief Retrieves computer system properties over dbus
+   *
+   * @param[in] aResp Shared pointer for completing asynchronous calls
+   * @param[in] name  Computer system name from request
+   *
+   * @return None.
+   */
+  void getComputerSystem(std::shared_ptr<SystemAsyncResp> aResp,
+                         const std::string &name) {
+    const std::array<const char *, 5> interfaces = {
+        "xyz.openbmc_project.Inventory.Decorator.Asset",
+        "xyz.openbmc_project.Inventory.Item.Cpu",
+        "xyz.openbmc_project.Inventory.Item.Dimm",
+        "xyz.openbmc_project.Inventory.Item.System",
+        "xyz.openbmc_project.Common.UUID",
+    };
+    CROW_LOG_DEBUG << "Get available system components.";
+    crow::connections::system_bus->async_method_call(
+        [ name, aResp{std::move(aResp)} ](
+            const boost::system::error_code ec,
+            const std::vector<std::pair<
+                std::string,
+                std::vector<std::pair<std::string, std::vector<std::string>>>>>
+                &subtree) {
+          if (ec) {
+            CROW_LOG_DEBUG << "DBUS response error";
+            aResp->setErrorStatus();
+            return;
+          }
+          bool foundName = false;
+          // Iterate over all retrieved ObjectPaths.
+          for (const std::pair<std::string,
+                               std::vector<std::pair<std::string,
+                                                     std::vector<std::string>>>>
+                   &object : subtree) {
+            const std::string &path = object.first;
+            CROW_LOG_DEBUG << "Got path: " << path;
+            const std::vector<std::pair<std::string, std::vector<std::string>>>
+                &connectionNames = object.second;
+            if (connectionNames.size() < 1) {
+              continue;
+            }
+            // Check if computer system exist
+            if (boost::ends_with(path, name)) {
+              foundName = true;
+              CROW_LOG_DEBUG << "Found name: " << name;
+              const std::string connectionName = connectionNames[0].first;
+              crow::connections::system_bus->async_method_call(
+                  [ aResp, name(std::string(name)) ](
+                      const boost::system::error_code ec,
+                      const std::vector<std::pair<std::string, VariantType>>
+                          &propertiesList) {
+                    if (ec) {
+                      CROW_LOG_ERROR << "DBUS response error: " << ec;
+                      aResp->setErrorStatus();
+                      return;
+                    }
+                    CROW_LOG_DEBUG << "Got " << propertiesList.size()
+                                   << "properties for system";
+                    for (const std::pair<std::string, VariantType> &property :
+                         propertiesList) {
+                      const std::string *value =
+                          mapbox::get_ptr<const std::string>(property.second);
+                      if (value != nullptr) {
+                        aResp->res.json_value[property.first] = *value;
+                      }
+                    }
+                    aResp->res.json_value["Name"] = name;
+                    aResp->res.json_value["Id"] =
+                        aResp->res.json_value["SerialNumber"];
+                  },
+                  connectionName, path, "org.freedesktop.DBus.Properties",
+                  "GetAll", "xyz.openbmc_project.Inventory.Decorator.Asset");
+            } else {
+              // This is not system, so check if it's cpu, dimm, UUID or BiosVer
+              for (auto const &s : connectionNames) {
+                for (auto const &i : s.second) {
+                  if (boost::ends_with(i, "Dimm")) {
+                    CROW_LOG_DEBUG << "Found Dimm, now get it properties.";
+                    crow::connections::system_bus->async_method_call(
+                        [&, aResp](const boost::system::error_code ec,
+                                   const std::vector<std::pair<
+                                       std::string, VariantType>> &properties) {
+                          if (ec) {
+                            CROW_LOG_ERROR << "DBUS response error " << ec;
+                            aResp->setErrorStatus();
+                            return;
+                          }
+                          CROW_LOG_DEBUG << "Got " << properties.size()
+                                         << "Dimm properties.";
+                          for (const auto &p : properties) {
+                            if (p.first == "MemorySize") {
+                              const std::string *value =
+                                  mapbox::get_ptr<const std::string>(p.second);
+                              if ((value != nullptr) && (*value != "NULL")) {
+                                // Remove units char
+                                int32_t unitCoeff;
+                                if (boost::ends_with(*value, "MB")) {
+                                  unitCoeff = 1000;
+                                } else if (boost::ends_with(*value, "KB")) {
+                                  unitCoeff = 1000000;
+                                } else {
+                                  CROW_LOG_ERROR << "Unsupported memory units";
+                                  aResp->setErrorStatus();
+                                  return;
+                                }
+
+                                auto memSize = boost::lexical_cast<int>(
+                                    value->substr(0, value->length() - 2));
+                                aResp->res.json_value["TotalSystemMemoryGiB"] +=
+                                    memSize * unitCoeff;
+                                aResp->res.json_value["MemorySummary"]["Status"]
+                                                     ["State"] = "Enabled";
+                              }
+                            }
+                          }
+                        },
+                        s.first, path, "org.freedesktop.DBus.Properties",
+                        "GetAll", "xyz.openbmc_project.Inventory.Item.Dimm");
+                  } else if (boost::ends_with(i, "Cpu")) {
+                    CROW_LOG_DEBUG << "Found Cpu, now get it properties.";
+                    crow::connections::system_bus->async_method_call(
+                        [&, aResp](const boost::system::error_code ec,
+                                   const std::vector<std::pair<
+                                       std::string, VariantType>> &properties) {
+                          if (ec) {
+                            CROW_LOG_ERROR << "DBUS response error " << ec;
+                            aResp->setErrorStatus();
+                            return;
+                          }
+                          CROW_LOG_DEBUG << "Got " << properties.size()
+                                         << "Cpu properties.";
+                          for (const auto &p : properties) {
+                            if (p.first == "ProcessorFamily") {
+                              const std::string *value =
+                                  mapbox::get_ptr<const std::string>(p.second);
+                              if (value != nullptr) {
+                                aResp->res
+                                    .json_value["ProcessorSummary"]["Count"] =
+                                    aResp->res
+                                        .json_value["ProcessorSummary"]["Count"]
+                                        .get<int>() +
+                                    1;
+                                aResp->res.json_value["ProcessorSummary"]
+                                                     ["Status"]["State"] =
+                                    "Enabled";
+                                aResp->res
+                                    .json_value["ProcessorSummary"]["Model"] =
+                                    *value;
+                              }
+                            }
+                          }
+                        },
+                        s.first, path, "org.freedesktop.DBus.Properties",
+                        "GetAll", "xyz.openbmc_project.Inventory.Item.Cpu");
+                  } else if (boost::ends_with(i, "UUID")) {
+                    CROW_LOG_DEBUG << "Found UUID, now get it properties.";
+                    crow::connections::system_bus->async_method_call(
+                        [aResp](const boost::system::error_code ec,
+                                const std::vector<std::pair<
+                                    std::string, VariantType>> &properties) {
+                          if (ec) {
+                            CROW_LOG_DEBUG << "DBUS response error " << ec;
+                            aResp->setErrorStatus();
+                            return;
+                          }
+                          CROW_LOG_DEBUG << "Got " << properties.size()
+                                         << "UUID properties.";
+                          for (const std::pair<std::string, VariantType> &p :
+                               properties) {
+                            if (p.first == "BIOSVer") {
+                              const std::string *value =
+                                  mapbox::get_ptr<const std::string>(p.second);
+                              if (value != nullptr) {
+                                aResp->res.json_value["BiosVersion"] = *value;
+                              }
+                            }
+                            if (p.first == "UUID") {
+                              const std::string *value =
+                                  mapbox::get_ptr<const std::string>(p.second);
+                              CROW_LOG_DEBUG << "UUID = " << *value
+                                             << " length " << value->length();
+                              if (value != nullptr) {
+                                // Workaround for to short return str in smbios
+                                // demo app, 32 bytes are described by spec
+                                if (value->length() > 0 &&
+                                    value->length() < 32) {
+                                  std::string correctedValue = *value;
+                                  correctedValue.append(32 - value->length(),
+                                                        '0');
+                                  value = &correctedValue;
+                                } else if (value->length() == 32) {
+                                  aResp->res.json_value["UUID"] =
+                                      value->substr(0, 8) + "-" +
+                                      value->substr(8, 4) + "-" +
+                                      value->substr(12, 4) + "-" +
+                                      value->substr(16, 4) + "-" +
+                                      value->substr(20, 12);
+                                }
+                              }
+                            }
+                          }
+                        },
+                        s.first, path, "org.freedesktop.DBus.Properties",
+                        "GetAll", "xyz.openbmc_project.Common.UUID");
+                  }
+                }
+              }
+            }
+          }
+          if (foundName == false) {
+            aResp->setErrorStatus();
+          }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+        "/xyz/openbmc_project/inventory", int32_t(0), interfaces);
+  }
+
+  /**
+   * @brief Retrieves identify led group properties over dbus
+   *
+   * @param[in] aResp     Shared pointer for completing asynchronous calls.
+   * @param[in] callback  Callback for process retrieved data.
+   *
+   * @return None.
+   */
+  template <typename CallbackFunc>
+  void getLedGroupIdentify(std::shared_ptr<SystemAsyncResp> aResp,
+                           CallbackFunc &&callback) {
+    CROW_LOG_DEBUG << "Get led groups";
+    crow::connections::system_bus->async_method_call(
+        [
+          aResp{std::move(aResp)}, &callback
+        ](const boost::system::error_code &ec, const ManagedObjectsType &resp) {
+          if (ec) {
+            CROW_LOG_DEBUG << "DBUS response error " << ec;
+            aResp->setErrorStatus();
+            return;
+          }
+          CROW_LOG_DEBUG << "Got " << resp.size() << "led group objects.";
+          for (const auto &objPath : resp) {
+            const std::string &path = objPath.first;
+            if (path.rfind("enclosure_identify") != std::string::npos) {
+              for (const auto &interface : objPath.second) {
+                if (interface.first == "xyz.openbmc_project.Led.Group") {
+                  for (const auto &property : interface.second) {
+                    if (property.first == "Asserted") {
+                      const bool *asserted =
+                          mapbox::get_ptr<const bool>(property.second);
+                      if (nullptr != asserted) {
+                        callback(*asserted, aResp);
+                      } else {
+                        callback(false, aResp);
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        },
+        "xyz.openbmc_project.LED.GroupManager",
+        "/xyz/openbmc_project/led/groups", "org.freedesktop.DBus.ObjectManager",
+        "GetManagedObjects");
+  }
+
+  template <typename CallbackFunc>
+  void getLedIdentify(std::shared_ptr<SystemAsyncResp> aResp,
+                      CallbackFunc &&callback) {
+    CROW_LOG_DEBUG << "Get identify led properties";
+    crow::connections::system_bus->async_method_call(
+        [ aResp{std::move(aResp)}, &callback ](
+            const boost::system::error_code ec,
+            const PropertiesType &properties) {
+          if (ec) {
+            CROW_LOG_DEBUG << "DBUS response error " << ec;
+            aResp->setErrorStatus();
+            return;
+          }
+          CROW_LOG_DEBUG << "Got " << properties.size() << "led properties.";
+          std::string output;
+          for (const auto &property : properties) {
+            if (property.first == "State") {
+              const std::string *s =
+                  mapbox::get_ptr<std::string>(property.second);
+              if (nullptr != s) {
+                CROW_LOG_DEBUG << "Identify Led State: " << *s;
+                const auto pos = s->rfind('.');
+                if (pos != std::string::npos) {
+                  auto led = s->substr(pos + 1);
+                  for (const std::pair<const char *, const char *> &p :
+                       std::array<std::pair<const char *, const char *>, 3>{
+                           {{"On", "Lit"},
+                            {"Blink", "Blinking"},
+                            {"Off", "Off"}}}) {
+                    if (led == p.first) {
+                      output = p.second;
+                    }
+                  }
+                }
+              }
+            }
+          }
+          callback(output, aResp);
+        },
+        "xyz.openbmc_project.LED.Controller.identify",
+        "/xyz/openbmc_project/led/physical/identify",
+        "org.freedesktop.DBus.Properties", "GetAll",
+        "xyz.openbmc_project.Led.Physical");
+  }
+
+  /**
+   * @brief Retrieves host state properties over dbus
+   *
+   * @param[in] aResp     Shared pointer for completing asynchronous calls.
+   *
+   * @return None.
+   */
+  void getHostState(std::shared_ptr<SystemAsyncResp> aResp) {
+    CROW_LOG_DEBUG << "Get host information.";
+    crow::connections::system_bus->async_method_call(
+        [aResp{std::move(aResp)}](const boost::system::error_code ec,
+                                  const PropertiesType &properties) {
+          if (ec) {
+            CROW_LOG_DEBUG << "DBUS response error " << ec;
+            aResp->setErrorStatus();
+            return;
+          }
+          CROW_LOG_DEBUG << "Got " << properties.size() << "host properties.";
+          for (const auto &property : properties) {
+            if (property.first == "CurrentHostState") {
+              const std::string *s =
+                  mapbox::get_ptr<const std::string>(property.second);
+              CROW_LOG_DEBUG << "Host state: " << *s;
+              if (nullptr != s) {
+                const auto pos = s->rfind('.');
+                if (pos != std::string::npos) {
+                  // Verify Host State
+                  if (s->substr(pos + 1) == "Running") {
+                    aResp->res.json_value["PowerState"] = "On";
+                    aResp->res.json_value["Status"]["State"] = "Enabled";
+                  } else {
+                    aResp->res.json_value["PowerState"] = "Off";
+                    aResp->res.json_value["Status"]["State"] = "Disabled";
+                  }
+                }
+              }
+            }
+          }
+        },
+        "xyz.openbmc_project.State.Host", "/xyz/openbmc_project/state/host0",
+        "org.freedesktop.DBus.Properties", "GetAll",
+        "xyz.openbmc_project.State.Host");
+  }
+};
+
+/**
+ * SystemsCollection derived class for delivering ComputerSystems Collection
+ * Schema
+ */
+class SystemsCollection : public Node {
+ public:
+  SystemsCollection(CrowApp &app) : Node(app, "/redfish/v1/Systems/") {
+    Node::json["@odata.type"] =
+        "#ComputerSystemCollection.ComputerSystemCollection";
+    Node::json["@odata.id"] = "/redfish/v1/Systems";
+    Node::json["@odata.context"] =
+        "/redfish/v1/"
+        "$metadata#ComputerSystemCollection.ComputerSystemCollection";
+    Node::json["Name"] = "Computer System Collection";
+
+    entityPrivileges = {
+        {boost::beast::http::verb::get, {{"Login"}}},
+        {boost::beast::http::verb::head, {{"Login"}}},
+        {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+        {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+        {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+        {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
+  }
+
+ private:
+  /**
+   * Functions triggers appropriate requests on DBus
+   */
+  void doGet(crow::response &res, const crow::request &req,
+             const std::vector<std::string> &params) override {
+    // Get board list, and call the below callback for JSON preparation
+    provider.getBaseboardList(
+        [&](const bool &success, const std::vector<std::string> &output) {
+          if (success) {
+            // ... prepare json array with appropriate @odata.id links
+            nlohmann::json boardArray = nlohmann::json::array();
+            for (const std::string &board_item : output) {
+              boardArray.push_back(
+                  {{"@odata.id", "/redfish/v1/Systems/" + board_item}});
+            }
+            // Then attach members, count size and return,
+            Node::json["Members"] = boardArray;
+            Node::json["Members@odata.count"] = boardArray.size();
+            res.json_value = Node::json;
+          } else {
+            // ... otherwise, return INTERNALL ERROR
+            res.result(boost::beast::http::status::internal_server_error);
+          }
+          res.end();
+        });
+  }
+
+  OnDemandSystemsProvider provider;
+};
+
+/**
+ * Systems override class for delivering ComputerSystems Schema
+ */
+class Systems : public Node {
+ public:
+  /*
+   * Default Constructor
+   */
+  Systems(CrowApp &app)
+      : Node(app, "/redfish/v1/Systems/<str>/", std::string()) {
+    Node::json["@odata.type"] = "#ComputerSystem.v1_3_0.ComputerSystem";
+    Node::json["@odata.context"] =
+        "/redfish/v1/$metadata#ComputerSystem.ComputerSystem";
+    Node::json["SystemType"] = "Physical";
+    Node::json["Description"] = "Computer System";
+    Node::json["Boot"]["BootSourceOverrideEnabled"] =
+        "Disabled";  // TODO(Dawid), get real boot data
+    Node::json["Boot"]["BootSourceOverrideTarget"] =
+        "None";  // TODO(Dawid), get real boot data
+    Node::json["Boot"]["BootSourceOverrideMode"] =
+        "Legacy";  // TODO(Dawid), get real boot data
+    Node::json["Boot"]["BootSourceOverrideTarget@Redfish.AllowableValues"] = {
+        "None",      "Pxe",       "Hdd", "Cd",
+        "BiosSetup", "UefiShell", "Usb"};  // TODO(Dawid), get real boot data
+    Node::json["ProcessorSummary"]["Count"] = int(0);
+    Node::json["ProcessorSummary"]["Status"]["State"] = "Disabled";
+    Node::json["MemorySummary"]["TotalSystemMemoryGiB"] = int(0);
+    Node::json["MemorySummary"]["Status"]["State"] = "Disabled";
+
+    entityPrivileges = {
+        {boost::beast::http::verb::get, {{"Login"}}},
+        {boost::beast::http::verb::head, {{"Login"}}},
+        {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
+        {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
+        {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
+        {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
+  }
+
+ private:
+  OnDemandSystemsProvider provider;
+
+  /**
+   * Functions triggers appropriate requests on DBus
+   */
+  void doGet(crow::response &res, const crow::request &req,
+             const std::vector<std::string> &params) override {
+    // Check if there is required param, truly entering this shall be
+    // impossible
+    if (params.size() != 1) {
+      res.result(boost::beast::http::status::internal_server_error);
+      res.end();
+      return;
+    }
+
+    const std::string &name = params[0];
+
+    res.json_value = Node::json;
+    res.json_value["@odata.id"] = "/redfish/v1/Systems/" + name;
+
+    auto asyncResp = std::make_shared<SystemAsyncResp>(res);
+
+    provider.getLedGroupIdentify(
+        asyncResp, [&](const bool &asserted,
+                       const std::shared_ptr<SystemAsyncResp> &aResp) {
+          if (asserted) {
+            // If led group is asserted, then another call is needed to
+            // get led status
+            provider.getLedIdentify(
+                aResp, [](const std::string &ledStatus,
+                          const std::shared_ptr<SystemAsyncResp> &aResp) {
+                  if (!ledStatus.empty()) {
+                    aResp->res.json_value["IndicatorLED"] = ledStatus;
+                  }
+                });
+          } else {
+            aResp->res.json_value["IndicatorLED"] = "Off";
+          }
+        });
+    provider.getComputerSystem(asyncResp, name);
+    provider.getHostState(asyncResp);
+  }
+
+  void doPatch(crow::response &res, const crow::request &req,
+               const std::vector<std::string> &params) override {
+    // Check if there is required param, truly entering this shall be
+    // impossible
+    if (params.size() != 1) {
+      res.result(boost::beast::http::status::internal_server_error);
+      res.end();
+      return;
+    }
+    // Parse JSON request body
+    nlohmann::json patch;
+    if (!json_util::processJsonFromRequest(res, req, patch)) {
+      return;
+    }
+    // Find key with new led value
+    const std::string &name = params[0];
+    const std::string *reqLedState = nullptr;
+    json_util::Result r = json_util::getString(
+        "IndicatorLED", patch, reqLedState,
+        static_cast<int>(json_util::MessageSetting::TYPE_ERROR) |
+            static_cast<int>(json_util::MessageSetting::MISSING),
+        res.json_value, std::string("/" + name + "/IndicatorLED"));
+    if ((r != json_util::Result::SUCCESS) || (reqLedState == nullptr)) {
+      res.result(boost::beast::http::status::bad_request);
+      res.end();
+      return;
+    }
+    // Verify key value
+    std::string dbusLedState;
+    for (const auto &p : boost::container::flat_map<const char *, const char *>{
+             {"On", "Lit"}, {"Blink", "Blinking"}, {"Off", "Off"}}) {
+      if (*reqLedState == p.second) {
+        dbusLedState = p.first;
+      }
+    }
+
+    // Update led status
+    auto asyncResp = std::make_shared<SystemAsyncResp>(res);
+    res.json_value = Node::json;
+    res.json_value["@odata.id"] = "/redfish/v1/Systems/" + name;
+
+    provider.getHostState(asyncResp);
+    provider.getComputerSystem(asyncResp, name);
+
+    if (dbusLedState.empty()) {
+      messages::addMessageToJsonRoot(
+          res.json_value,
+          messages::propertyValueNotInList(*reqLedState, "IndicatorLED"));
+    } else {
+      // Update led group
+      CROW_LOG_DEBUG << "Update led group.";
+      crow::connections::system_bus->async_method_call(
+          [&, asyncResp{std::move(asyncResp)} ](
+              const boost::system::error_code ec) {
+            if (ec) {
+              CROW_LOG_DEBUG << "DBUS response error " << ec;
+              asyncResp->setErrorStatus();
+              return;
+            }
+            CROW_LOG_DEBUG << "Led group update done.";
+          },
+          "xyz.openbmc_project.LED.GroupManager",
+          "/xyz/openbmc_project/led/groups/enclosure_identify",
+          "org.freedesktop.DBus.Properties", "Set",
+          "xyz.openbmc_project.Led.Group", "Asserted",
+          sdbusplus::message::variant<bool>(
+              (dbusLedState == "Off" ? false : true)));
+      // Update identify led status
+      CROW_LOG_DEBUG << "Update led SoftwareInventoryCollection.";
+      crow::connections::system_bus->async_method_call(
+          [&, asyncResp{std::move(asyncResp)} ](
+              const boost::system::error_code ec) {
+            if (ec) {
+              CROW_LOG_DEBUG << "DBUS response error " << ec;
+              asyncResp->setErrorStatus();
+              return;
+            }
+            CROW_LOG_DEBUG << "Led state update done.";
+            res.json_value["IndicatorLED"] = *reqLedState;
+          },
+          "xyz.openbmc_project.LED.Controller.identify",
+          "/xyz/openbmc_project/led/physical/identify",
+          "org.freedesktop.DBus.Properties", "Set",
+          "xyz.openbmc_project.Led.Physical", "State",
+          sdbusplus::message::variant<std::string>(
+              "xyz.openbmc_project.Led.Physical.Action." + dbusLedState));
+    }
+  }
+};
+}  // namespace redfish
