summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Kodihalli <dkodihal@in.ibm.com>2017-04-12 06:40:53 -0500
committerDeepak Kodihalli <dkodihal@in.ibm.com>2017-04-18 11:54:17 -0500
commit059e23355e0563ed22661ec2a78ccdc563414a7d (patch)
treebad284e0c2dd7e730cdc291b084be951c064b663
parent7f160bc8fa94fbec69a15ab707f10f6d0122ca8b (diff)
downloadphosphor-bmc-code-mgmt-059e23355e0563ed22661ec2a78ccdc563414a7d.tar.gz
phosphor-bmc-code-mgmt-059e23355e0563ed22661ec2a78ccdc563414a7d.zip
image manager: add inotify watch
Add an inotify watch to the known software image location. Hook the inotify fd with sd-event, so that on callback, version d-bus objects can be created based on the newly added software image. Resolves openbmc/openbmc#1444. Change-Id: I5c460f820c8d3a851b8ddc969f26d38870c36991 Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
-rwxr-xr-xMakefile.am21
-rwxr-xr-xconfigure.ac6
-rw-r--r--image_manager_main.cpp25
-rw-r--r--watch.cpp104
-rw-r--r--watch.hpp60
5 files changed, 206 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index 1e863d7..e4be065 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,19 +1,34 @@
AM_DEFAULT_SOURCE_EXT = .cpp
+# Build these headers, don't install them
+noinst_HEADERS = \
+ version_software_manager.hpp \
+ download_manager.hpp \
+ watch.hpp
+
sbin_PROGRAMS = \
phosphor-version-software-manager \
phosphor-download-manager
phosphor_version_software_manager_SOURCES = \
version_software_manager.cpp \
- image_manager_main.cpp
+ image_manager_main.cpp \
+ watch.cpp
phosphor_download_manager_SOURCES = \
download_manager.cpp \
download_manager_main.cpp
-generic_cxxflags = $(SYSTEMD_CFLAGS) $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) $(SDBUSPLUS_CFLAGS)
-generic_ldflags = $(SYSTEMD_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS) $(SDBUSPLUS_LIBS)
+generic_cxxflags = \
+ $(SYSTEMD_CFLAGS) \
+ $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
+ $(SDBUSPLUS_CFLAGS) \
+ $(PHOSPHOR_LOGGING_CFLAGS)
+generic_ldflags = \
+ $(SYSTEMD_LIBS) \
+ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \
+ $(SDBUSPLUS_LIBS) \
+ $(PHOSPHOR_LOGGING_LIBS)
phosphor_version_software_manager_CXXFLAGS = $(generic_cxxflags)
phosphor_version_software_manager_LDFLAGS = $(generic_ldflags)
diff --git a/configure.ac b/configure.ac
index af227ae..1928422 100755
--- a/configure.ac
+++ b/configure.ac
@@ -16,6 +16,8 @@ PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces],,\
AC_MSG_ERROR(["Requires phosphor-dbus-interfaces package."]))
PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus],,
AC_MSG_ERROR(["Requires sdbusplus package."]))
+PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],,\
+ AC_MSG_ERROR(["Requires phosphor-logging package."]))
# Checks for library functions
LT_INIT # Required for systemd linking
@@ -37,6 +39,10 @@ AS_IF([test "x$DOWNLOAD_BUSNAME" == "x"],
[DOWNLOAD_BUSNAME="xyz.openbmc_project.Software.Download"])
AC_DEFINE_UNQUOTED([DOWNLOAD_BUSNAME], ["$DOWNLOAD_BUSNAME"], [The DBus busname to own])
+AC_ARG_VAR(IMG_UPLOAD_DIR, [Directory where downloaded software images are placed])
+AS_IF([test "x$IMG_UPLOAD_DIR" == "x"], [IMG_UPLOAD_DIR="/tmp/images"])
+AC_DEFINE_UNQUOTED([IMG_UPLOAD_DIR], ["$IMG_UPLOAD_DIR"], [Directory where downloaded software images are placed])
+
# Check for header files.
AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd developement package required])])
AC_CHECK_HEADER(sdbusplus/server.hpp, ,[AC_MSG_ERROR([Could not find sdbusplus/server.hpp...openbmc/sdbusplus package required])])
diff --git a/image_manager_main.cpp b/image_manager_main.cpp
index bd41b63..66f31f6 100644
--- a/image_manager_main.cpp
+++ b/image_manager_main.cpp
@@ -1,27 +1,38 @@
-#include <iostream>
#include <cstdlib>
#include <exception>
#include <sdbusplus/bus.hpp>
+#include <phosphor-logging/log.hpp>
#include "config.h"
#include "version_software_manager.hpp"
+#include "watch.hpp"
int main(int argc, char* argv[])
{
auto bus = sdbusplus::bus::new_default();
- // Add sdbusplus ObjectManager.
+ sd_event* loop = nullptr;
+ sd_event_default(&loop);
+
sdbusplus::server::manager::manager objManager(bus,
SOFTWARE_OBJPATH);
-
phosphor::software::manager::Version manager(bus,
SOFTWARE_OBJPATH);
-
bus.request_name(VERSION_BUSNAME);
- while (true)
+ try
{
- bus.process_discard();
- bus.wait();
+ phosphor::software::manager::Watch watch(loop);
+ bus.attach_event(loop, SD_EVENT_PRIORITY_NORMAL);
+ sd_event_loop(loop);
}
+ catch (std::exception& e)
+ {
+ using namespace phosphor::logging;
+ log<level::ERR>(e.what());
+ return -1;
+ }
+
+ sd_event_unref(loop);
+
return 0;
}
diff --git a/watch.cpp b/watch.cpp
new file mode 100644
index 0000000..a520dd2
--- /dev/null
+++ b/watch.cpp
@@ -0,0 +1,104 @@
+#include <stdexcept>
+#include <cstddef>
+#include <cstring>
+#include <string>
+#include <sys/inotify.h>
+#include <unistd.h>
+#include <phosphor-logging/log.hpp>
+#include "config.h"
+#include "watch.hpp"
+
+namespace phosphor
+{
+namespace software
+{
+namespace manager
+{
+
+using namespace std::string_literals;
+
+Watch::Watch(sd_event* loop)
+{
+ fd = inotify_init1(IN_NONBLOCK);
+ if (-1 == fd)
+ {
+ // Store a copy of errno, because the string creation below will
+ // invalidate errno due to one more system calls.
+ auto error = errno;
+ throw std::runtime_error(
+ "inotify_init1 failed, errno="s + std::strerror(error));
+ }
+
+ wd = inotify_add_watch(fd, IMG_UPLOAD_DIR, IN_CREATE);
+ if (-1 == wd)
+ {
+ auto error = errno;
+ close(fd);
+ throw std::runtime_error(
+ "inotify_add_watch failed, errno="s + std::strerror(error));
+ }
+
+ auto rc = sd_event_add_io(loop,
+ nullptr,
+ fd,
+ EPOLLIN,
+ callback,
+ this);
+ if (0 > rc)
+ {
+ throw std::runtime_error(
+ "failed to add to event loop, rc="s + std::strerror(-rc));
+ }
+}
+
+Watch::~Watch()
+{
+ if ((-1 != fd) && (-1 != wd))
+ {
+ inotify_rm_watch(fd, wd);
+ close(fd);
+ }
+}
+
+int Watch::callback(sd_event_source* s,
+ int fd,
+ uint32_t revents,
+ void* userdata)
+{
+ if (!(revents & EPOLLIN))
+ {
+ return 0;
+ }
+
+ constexpr auto maxBytes = 1024;
+ uint8_t buffer[maxBytes];
+ auto bytes = read(fd, buffer, maxBytes);
+ if (0 > bytes)
+ {
+ auto error = errno;
+ throw std::runtime_error(
+ "failed to read inotify event, errno="s + std::strerror(error));
+ }
+
+ auto offset = 0;
+ while (offset < bytes)
+ {
+ auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
+ if ((event->mask & IN_CREATE) && !(event->mask & IN_ISDIR))
+ {
+ // TODO: openbmc/openbmc#1352 - invoke method (which takes uploaded
+ // filepath) to construct software version d-bus objects.
+ // For now, log the image filename.
+ using namespace phosphor::logging;
+ log<level::INFO>(event->name);
+ }
+
+ offset += offsetof(inotify_event, name) + event->len;
+ }
+
+ return 0;
+}
+
+} // namespace manager
+} // namespace software
+} // namespace phosphor
diff --git a/watch.hpp b/watch.hpp
new file mode 100644
index 0000000..c125ef2
--- /dev/null
+++ b/watch.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include <systemd/sd-event.h>
+
+namespace phosphor
+{
+namespace software
+{
+namespace manager
+{
+
+/** @class Watch
+ *
+ * @brief Adds inotify watch on software image upload directory
+ *
+ * The inotify watch is hooked up with sd-event, so that on call back,
+ * appropriate actions related to a software image upload can be taken.
+ */
+class Watch
+{
+ public:
+ /** @brief ctor - hook inotify watch with sd-event
+ *
+ * @param[in] loop - sd-event object
+ */
+ Watch(sd_event* loop);
+
+ Watch(const Watch&) = delete;
+ Watch& operator=(const Watch&) = delete;
+ Watch(Watch&&) = default;
+ Watch& operator=(Watch&&) = default;
+
+ /** @brief dtor - remove inotify watch and close fd's
+ */
+ ~Watch();
+
+ private:
+ /** @brief sd-event callback
+ *
+ * @param[in] s - event source, floating (unused) in our case
+ * @param[in] fd - inotify fd
+ * @param[in] revents - events that matched for fd
+ * @param[in] userdata - pointer to Watch object
+ * @returns 0 on success, -1 on fail
+ */
+ static int callback(sd_event_source* s,
+ int fd,
+ uint32_t revents,
+ void* userdata);
+
+ /** @brief image upload directory watch descriptor */
+ int wd = -1;
+
+ /** @brief inotify file descriptor */
+ int fd = -1;
+};
+
+} // namespace manager
+} // namespace software
+} // namespace phosphor
OpenPOWER on IntegriCloud