Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement vpd-tool dump inventory #498

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions vpd-tool/include/tool_constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ namespace constants
{
static constexpr auto KEYWORD_SIZE = 2;
static constexpr auto RECORD_SIZE = 4;
static constexpr auto INDENTATION = 4;

constexpr auto inventoryManagerService =
"xyz.openbmc_project.Inventory.Manager";
constexpr auto baseInventoryPath = "/xyz/openbmc_project/inventory";
constexpr auto ipzVpdInfPrefix = "com.ibm.ipzvpd.";
constexpr auto ipzVpdInf = "com.ibm.ipzvpd.";
constexpr auto inventoryItemInf = "xyz.openbmc_project.Inventory.Item";
constexpr auto kwdVpdInf = "com.ibm.ipzvpd.VINI";
constexpr auto locationCodeInf = "com.ibm.ipzvpd.Location";
constexpr auto assetInf = "xyz.openbmc_project.Inventory.Decorator.Asset";
} // namespace constants
} // namespace vpd
51 changes: 51 additions & 0 deletions vpd-tool/include/tool_json_utility.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <nlohmann/json.hpp>

#include <fstream>

namespace vpd
{
namespace jsonUtility
{

/**
* @brief API to parse respective JSON.
*
* Exception is thrown in case of JSON parse error.
*
* @param[in] pathToJson - Path to JSON.
* @return Parsed JSON.
* @throw std::runtime_error
*/
inline nlohmann::json getParsedJson(const std::string& pathToJson)
{
if (pathToJson.empty())
{
throw std::runtime_error("Path to JSON is missing");
}

if (!std::filesystem::exists(pathToJson) ||
std::filesystem::is_empty(pathToJson))
{
throw std::runtime_error("Incorrect File Path or empty file");
}

std::ifstream jsonFile(pathToJson);
if (!jsonFile)
{
throw std::runtime_error("Failed to access Json path = " + pathToJson);
}

try
{
return nlohmann::json::parse(jsonFile);
}
catch (const nlohmann::json::parse_error& e)
{
throw std::runtime_error("Failed to parse JSON file");
}
}

} // namespace jsonUtility
} // namespace vpd
44 changes: 44 additions & 0 deletions vpd-tool/include/tool_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <sdbusplus/message/types.hpp>

#include <cstdint>
#include <tuple>
#include <variant>
#include <vector>

namespace vpd
{
namespace types
{
using BinaryVector = std::vector<uint8_t>;

// This covers mostly all the data type supported over DBus for a property.
// clang-format off
using DbusVariantType = std::variant<
std::vector<std::tuple<std::string, std::string, std::string>>,
std::vector<std::string>,
std::vector<double>,
std::string,
int64_t,
uint64_t,
double,
int32_t,
uint32_t,
int16_t,
uint16_t,
uint8_t,
bool,
BinaryVector,
std::vector<uint32_t>,
std::vector<uint16_t>,
sdbusplus::message::object_path,
std::tuple<uint64_t, std::vector<std::tuple<std::string, std::string, double, uint64_t>>>,
std::vector<std::tuple<std::string, std::string>>,
std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>,
std::vector<std::tuple<uint32_t, size_t>>,
std::vector<std::tuple<sdbusplus::message::object_path, std::string,
std::string, std::string>>
>;
} // namespace types
} // namespace vpd
128 changes: 128 additions & 0 deletions vpd-tool/include/utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#pragma once

#include "tool_constants.hpp"
#include "tool_types.hpp"

#include <nlohmann/json.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/exception.hpp>

#include <iostream>

namespace vpd
{
namespace utils
{
/**
* @brief An API to read property from Dbus.
*
* API reads the property value for the specified interface and object path from
* the given Dbus service.
*
* The caller of the API needs to validate the validity and correctness of the
* type and value of data returned. The API will just fetch and return the data
* without any data validation.
*
* Note: It will be caller's responsibility to check for empty value returned
* and generate appropriate error if required.
*
* @param[in] i_serviceName - Name of the Dbus service.
* @param[in] i_objectPath - Object path under the service.
* @param[in] i_interface - Interface under which property exist.
* @param[in] i_property - Property whose value is to be read.
*
* @return - Value read from Dbus, if success.
* If failed, empty variant.
*/
inline types::DbusVariantType readDbusProperty(const std::string& i_serviceName,
const std::string& i_objectPath,
const std::string& i_interface,
const std::string& i_property)
{
types::DbusVariantType l_propertyValue;

// Mandatory fields to make a dbus call.
if (i_serviceName.empty() || i_objectPath.empty() || i_interface.empty() ||
i_property.empty())
{
// TODO: Enable logging when verbose is enabled.
/*std::cout << "One of the parameter to make Dbus read call is empty."
<< std::endl;*/
return l_propertyValue;
}

try
{
auto l_bus = sdbusplus::bus::new_default();
auto l_method =
l_bus.new_method_call(i_serviceName.c_str(), i_objectPath.c_str(),
"org.freedesktop.DBus.Properties", "Get");
l_method.append(i_interface, i_property);

auto result = l_bus.call(l_method);
result.read(l_propertyValue);
}
catch (const sdbusplus::exception::SdBusError& l_ex)
{
// TODO: Enable logging when verbose is enabled.
// std::cout << std::string(l_ex.what()) << std::endl;
}
return l_propertyValue;
}

/**
* @brief An API to print json data on stdout.
*
* @param[in] i_jsonData - JSON object.
*/
inline void printJson(const nlohmann::json& i_jsonData)
{
try
{
std::cout << i_jsonData.dump(constants::INDENTATION) << std::endl;
}
catch (const nlohmann::json::type_error& l_ex)
{
throw std::runtime_error("Failed to dump JSON data, error: " +
std::string(l_ex.what()));
}
}

/**
* @brief An API to convert hex value to string.
*
* If given data contains printable characters, ASCII formated string value of
* the input data will be returned. Otherwise if the data has any non-printable
* value, returns the hex represented value of the given data in string format.
*
* @param[in] i_keywordValue - Data in hex.
*
* @throw - Throws std::bad_alloc or std::terminate in case of error.
*
* @return - Returns the converted string value.
*/
inline std::string getPrintableValue(const types::BinaryVector& i_keywordValue)
{
bool l_allPrintable =
std::all_of(i_keywordValue.begin(), i_keywordValue.end(),
[](const auto& l_byte) { return std::isprint(l_byte); });

std::ostringstream l_oss;
if (l_allPrintable)
{
l_oss << std::string(i_keywordValue.begin(), i_keywordValue.end());
}
else
{
l_oss << "0x";
for (const auto& l_byte : i_keywordValue)
{
l_oss << std::setfill('0') << std::setw(2) << std::hex
<< static_cast<int>(l_byte);
}
}

return l_oss.str();
}
} // namespace utils
} // namespace vpd
69 changes: 69 additions & 0 deletions vpd-tool/include/vpd_tool.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "utils.hpp"

#include <string>

namespace vpd
Expand All @@ -17,6 +19,44 @@ namespace vpd
*/
class VpdTool
{
/**
* @brief Get any Inventory Propery in JSON.
*
* API to get any property of a FRU in JSON format.
*
* @param[in] i_objectPath - DBus object path
*
* @param[in] i_interface - Interface name
*
* @param[in] i_propertyName - Property name
*
* @return On success, returns the property and its value in JSON format,
* otherwise return empty JSON.
* {"SN" : "ABCD"}
*
* @throw Does not throw
*/
template <typename PropertyType>
nlohmann::json getInventoryPropertyJson(
const std::string& i_objectPath, const std::string& i_interface,
const std::string& i_propertyName) const noexcept;

/**
* @brief Get VINI properties.
*
* API to get properties [SN, PN, CC, FN, DR] under VINI interface in JSON
* format.
*
* @param[in] i_fruPath - DBus object path.
*
* @return On success, returns JSON output with the above properties under
* VINI interface, otherwise returns empty JSON.
*
* @throw Does not throw.
*/
nlohmann::json
getVINIPropertiesJson(const std::string& i_fruPath) const noexcept;

public:
/**
* @brief Read keyword value.
Expand All @@ -39,5 +79,34 @@ class VpdTool
const std::string& i_recordName,
const std::string& i_keywordName, const bool i_onHardware,
const std::string& i_fileToSave = {});

/**
* @brief Dump the given inventory object in JSON format.
*
* For a given Object Path of a FRU, this API dumps the following properties
* of the FRU in JSON format:
* - Present property, Pretty Name, Location Code, Sub Model
* - SN, PN, CC, FN, DR keywords under VINI record.
*
* @param[in] i_fruPath - DBus object path.
*
* @param[in] io_resultJson - JSON object which holds the result.
*
* @return On success returns 0, otherwise returns -1.
*/
int dumpObject(const std::string& i_fruPath,
nlohmann::json& io_resultJson) const noexcept;

/**
* @brief Dump all the objects in Inventory in JSON format.
*
* This API dumps the following properties
* of all the FRUs in the Inventory in JSON format:
* - Present property, Pretty Name, Location Code, Sub Model
* - SN, PN, CC, FN, DR keywords under VINI record.
*
* @return On success returns 0, otherwise returns -1.
*/
int dumpInventory() const noexcept;
};
} // namespace vpd
8 changes: 7 additions & 1 deletion vpd-tool/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ else
CLI11_dep = dependency('CLI11')
endif

dependency_list = [CLI11_dep]
sdbusplus = dependency('sdbusplus', fallback: [ 'sdbusplus', 'sdbusplus_dep' ])
dependency_list = [CLI11_dep, sdbusplus]

conf_data = configuration_data()
conf_data.set_quoted('INVENTORY_JSON_SYM_LINK', get_option('INVENTORY_JSON_SYM_LINK'))
configure_file(output: 'config.h',
configuration : conf_data)

sources = ['src/vpd_tool_main.cpp',
'src/vpd_tool.cpp']
Expand Down
1 change: 1 addition & 0 deletions vpd-tool/meson.options
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
option('INVENTORY_JSON_SYM_LINK', type: 'string', value: '/var/lib/vpd/vpd_inventory.json', description: 'Symbolic link to vpd inventory json.')
Loading