REST: Add DELETE support

Add support for the DELETE verb.  This verb will cause the
Delete method on the xyz.openbmc_project.Object.Delete interface
to be called on the specified object path.  An error will be
returned if that interface/method doesn't exist on that path.

The code is similar to the method handling code, except it
doesn't need to parse any argument JSON, and it is looking only
at a specific interface.  It does share the code path that
introspects the object to find a method and call it.

Tested:  Used it to delete error logs.

Change-Id: Ica90b0d80049e6bc59fe2b8456948696054f4a8b
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp
index 4a34f5c..c3908ca 100644
--- a/include/openbmc_dbus_rest.hpp
+++ b/include/openbmc_dbus_rest.hpp
@@ -417,6 +417,7 @@
     crow::Response &res;
     std::string path;
     std::string methodName;
+    std::string interfaceName;
     nlohmann::json arguments;
 };
 
@@ -783,6 +784,14 @@
                         interfaceNode->Attribute("name");
                     if (thisInterfaceName != nullptr)
                     {
+                        if (!transaction->interfaceName.empty() &&
+                            (transaction->interfaceName != thisInterfaceName))
+                        {
+                            interfaceNode =
+                                interfaceNode->NextSiblingElement("interface");
+                            continue;
+                        }
+
                         tinyxml2::XMLElement *methodNode =
                             interfaceNode->FirstChildElement("method");
                         while (methodNode != nullptr)
@@ -939,6 +948,42 @@
         std::array<std::string, 0>());
 }
 
+void handleDelete(const crow::Request &req, crow::Response &res,
+                  const std::string &objectPath)
+{
+    BMCWEB_LOG_DEBUG << "handleDelete on path: " << objectPath;
+
+    crow::connections::systemBus->async_method_call(
+        [&res, objectPath](
+            const boost::system::error_code ec,
+            const std::vector<std::pair<std::string, std::vector<std::string>>>
+                &interfaceNames) {
+            if (ec || interfaceNames.size() <= 0)
+            {
+                BMCWEB_LOG_ERROR << "Can't find object";
+                setErrorResponse(res, boost::beast::http::status::not_found,
+                                 notFoundDesc, notFoundMsg);
+                res.end();
+                return;
+            }
+
+            auto transaction = std::make_shared<InProgressActionData>(res);
+            transaction->path = objectPath;
+            transaction->methodName = "Delete";
+            transaction->interfaceName = "xyz.openbmc_project.Object.Delete";
+
+            for (const std::pair<std::string, std::vector<std::string>>
+                     &object : interfaceNames)
+            {
+                findActionOnInterface(transaction, object.first);
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetObject", objectPath,
+        std::array<const char *, 0>());
+}
+
 void handleList(crow::Response &res, const std::string &objectPath,
                 int32_t depth = 0)
 {
@@ -1393,6 +1438,11 @@
         handlePut(req, res, objectPath, destProperty);
         return;
     }
+    else if (req.method() == "DELETE"_method)
+    {
+        handleDelete(req, res, objectPath);
+        return;
+    }
 
     setErrorResponse(res, boost::beast::http::status::method_not_allowed,
                      methodNotAllowedDesc, methodNotAllowedMsg);
@@ -1444,7 +1494,7 @@
             });
 
     BMCWEB_ROUTE(app, "/xyz/<path>")
-        .methods("GET"_method, "PUT"_method, "POST"_method)(
+        .methods("GET"_method, "PUT"_method, "POST"_method, "DELETE"_method)(
             [](const crow::Request &req, crow::Response &res,
                const std::string &path) {
                 std::string objectPath = "/xyz/" + path;
@@ -1452,7 +1502,7 @@
             });
 
     BMCWEB_ROUTE(app, "/org/<path>")
-        .methods("GET"_method, "PUT"_method, "POST"_method)(
+        .methods("GET"_method, "PUT"_method, "POST"_method, "DELETE"_method)(
             [](const crow::Request &req, crow::Response &res,
                const std::string &path) {
                 std::string objectPath = "/org/" + path;