Closed 128keaton closed 12 months ago
https://github.com/openbmc/phosphor-state-manager/blob/master/chassis_state_manager.cpp#L81
Some linked example with a very complex structure.
Maybe we can just monitor the processes and report status updates using dbus: https://stackoverflow.com/questions/61940461/how-to-get-the-state-of-a-service-with-sd-bus
Then we can just have a basic binary that generates services with parameters: https://stackoverflow.com/questions/62474719/creating-and-loading-a-systemd-service-from-a-c-program
I can get started with a few tutorials on dbus.
https://unix.stackexchange.com/a/675213 has a great reference:
#include <systemd/sd-bus.h>
static void CallMethodSS(
sd_bus* bus,
const std::string& name,
const std::string& method)
{
sd_bus_error err = SD_BUS_ERROR_NULL;
sd_bus_message* msg = nullptr;
int r;
r = sd_bus_call_method(bus,
"org.freedesktop.systemd1", /* <service> */
"/org/freedesktop/systemd1", /* <path> */
"org.freedesktop.systemd1.Manager", /* <interface> */
method.c_str(), /* <method> */
&err, /* object to return error in */
&msg, /* return message on success */
"ss", /* <input_signature (string-string)> */
name.c_str(), "replace" ); /* <arguments...> */
if (r < 0)
{
std::string err_str("Could not send " + method +
" command to systemd for service: " + name +
". Error: " + err.message );
sd_bus_error_free(&err);
sd_bus_message_unref(msg);
throw exception(err_str);
}
// Extra stuff that might be useful: display the response...
char* response;
r = sd_bus_message_read(msg, "o", &response);
if (r < 0)
{
LogError("Failed to parse response message: %s\n", strerror(-r) );
}
sd_bus_error_free(&err);
sd_bus_message_unref(msg);
}
I plan to install the two unit files for the daemons under /etc/systemd/system/
, meaning names should be mappable to each service out of the box:
This daemon will need to run as root to start and enable (EnableUnitFiles()
) so we will need to communicate with this daemon somehow without calling root. I think a Unix Domain Socket should work with JSON, see here where I am doing this already with Janus
You can see here in Never Gateway that I am expecting a Unix Domain Socket somewhere like /tmp/nvr-gw-sock
I am expecting it to be a DGRAM
socket for ease of debugging right now.
This is where the primary communication to the API gateway will take place. The binary here should create and monitor this socket for any messages. Right now the messages are constructed like shown:
{
"name": "new",
"configPath": "/nvr/cameras/camera-1.json"
}
Note that name
can be new
, update
, or delete
, since this binary should handle those events.
Also note that the name of the recording/streaming services are expected to be something like nvr-stream@camera-1
.
If you notice, the configuration file's name (without extension) matches the end of that service descriptor, and this is on purpose.
The event new
should trigger the enablement of the NVR service and start it for said camera configuration.
The event update
should trigger a restart/reload of the NVR service for said camera configuration (the event is sent after the configuration has been changed on-disk)
The event delete
should trigger the disablement/stoppage of the NVR service for said camera configuration.
The camera_status_manager is able to create camera-x.json files in /nvr/cameras/. Now working on starting the camera daemons.
The created binary can now start nvr-record@camera-x.service upon creating a camera JSON.
If we'd like to use C++ natively, there is dbus, @aysent911 do you have any experience with dbus?
Otherwise, we can use bash scripts (not as great).
The idea is that we can tell this binary when a camera was deleted, updated, or added.
If created, it will generate the camera's JSON from input and then create and start the service. If deleted, it will stop and remove the service. If updated, it will regenerate the camera's JSON from input and then restart the service