We spoke about this a little in the last team meeting, the consensus was that we'd like to include the functionality in the host agent. Would that be acceptable? Some of the function names might need tweaking as a result (to indicate what kind of profiles are being set).
Other comments in-line.
On Mon, May 30, 2011 at 6:46 PM, Jaroslav Škarvada jskarvad@redhat.com wrote:
Thanks for your comments. I tried to incorporate all of them. In the previous version of patch a lot of code was taken from the other agents, so it should be fixed there as well.
I also rewrote the Win & Lin exec funcs to be more consistent. Now it could be probably merged into one code, put into utilities.c and reused in other agents (e.g. services).
I also tried to fix some minor bugs (and hopefully didn't introduced new ones :) The functionality was re-tested again on Win & Lin
thanks & regards
Jaroslav
CMakeLists.txt | 6 + matahari.spec | 45 ++++++ src/CMakeLists.txt | 1 + src/include/matahari/pm.h | 70 +++++++++ src/lib/CMakeLists.txt | 10 +- src/lib/pm.c | 45 ++++++ src/lib/pm_linux.c | 259 +++++++++++++++++++++++++++++++++ src/lib/pm_private.h | 39 +++++ src/lib/pm_windows.c | 241 ++++++++++++++++++++++++++++++ src/pm/CMakeLists.txt | 61 ++++++++ src/pm/org.matahariproject.PM.conf | 18 +++ src/pm/org.matahariproject.PM.policy | 27 ++++ src/pm/org.matahariproject.PM.service | 4 + src/pm/pm-dbus.c | 142 ++++++++++++++++++ src/pm/pm-qmf.cpp | 107 ++++++++++++++ src/pm/schema.xml | 21 +++ src/schema.xml | 18 +++ src/windows/install.bat | 2 +- 18 files changed, 1112 insertions(+), 4 deletions(-) create mode 100644 src/include/matahari/pm.h create mode 100644 src/lib/pm.c create mode 100644 src/lib/pm_linux.c create mode 100644 src/lib/pm_private.h create mode 100644 src/lib/pm_windows.c create mode 100644 src/pm/CMakeLists.txt create mode 100644 src/pm/org.matahariproject.PM.conf create mode 100644 src/pm/org.matahariproject.PM.policy create mode 100644 src/pm/org.matahariproject.PM.service create mode 100644 src/pm/pm-dbus.c create mode 100644 src/pm/pm-qmf.cpp create mode 100644 src/pm/schema.xml
diff --git a/CMakeLists.txt b/CMakeLists.txt index e4daf05..328b02e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,15 +79,18 @@ if(WIN32) set( CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} " Some comment\n DetailPrint \"Stopping Matahari services\"\n" " Some comment\n ExecWait '\"$SYSDIR\\sc.exe stop mh_hostd\"'\n"
- " Some comment\n ExecWait '\"$SYSDIR\\sc.exe stop mh_pmd\"'\n"
" Some comment\n ExecWait '\"$SYSDIR\\sc.exe stop mh_netd\"'\n" " Some comment\n ExecWait '\"$SYSDIR\\sc.exe stop mh_serviced\"'\n" " Give them time to stop\n Sleep 10000\n" " Some comment\n DetailPrint \"Removing Matahari services\"\n" " Some comment\n ExecWait '\"$SYSDIR\\sc.exe delete mh_hostd\"'\n"
- " Some comment\n ExecWait '\"$SYSDIR\\sc.exe delete mh_pmd\"'\n"
" Some comment\n ExecWait '\"$SYSDIR\\sc.exe delete mh_netd\"'\n" " Some comment\n ExecWait '\"$SYSDIR\\sc.exe delete mh_serviced\"'\n" " Some comment\n DetailPrint \"Removing Matahari service binaries\"\n" " Some comment\n ExecWait 'del \"$INSTDIR\\mh_hostd.exe\"'\n"
- " Some comment\n ExecWait 'del \"$INSTDIR\\mh_pmd.exe\"'\n"
" Some comment\n ExecWait 'del \"$INSTDIR\\mh_netd.exe\"'\n" " Some comment\n ExecWait 'del \"$INSTDIR\\mh_serviced.exe\"'\n" ) @@ -105,6 +108,9 @@ if(WIN32) install(FILES ${SRVANY_EXE} DESTINATION sbin) install(FILES src/windows/install.bat DESTINATION sbin)
- # gspawn-win32-helper-console
- file(GLOB_RECURSE GSPAWN_HELPER_CONSOLE_EXE ${MINGW_ROOT}/*/gspawn-win32-helper-console.exe)
- install(FILES ${GSPAWN_HELPER_CONSOLE_EXE} DESTINATION sbin)
else(WIN32)
set (CPACK_GENERATOR "TGZ") diff --git a/matahari.spec b/matahari.spec index a52b1d7..f0e8ffa 100644 --- a/matahari.spec +++ b/matahari.spec @@ -107,6 +107,17 @@ Requires: %{name}-agent-lib = %{version}-%{release} %description host QMF agent for viewing and controlling remote hosts
+%package pm +License: GPLv2+ +Summary: QMF agent for PM +Group: Applications/System +Requires: %{name}-lib = %{version}-%{release} +Requires: %{name}-agent-lib = %{version}-%{release} +Requires: tuned
+%description pm +QMF agent for viewing and controlling power management settings
%package network License: GPLv2+ Summary: QMF agent for network devices @@ -202,6 +213,22 @@ if [ "$1" -ge "1" ]; then /sbin/service matahari-host condrestart >/dev/null 2>&1 || : fi
+#== PM
+%post pm +/sbin/service matahari-pm condrestart
+%preun pm +if [ $1 = 0 ]; then
- /sbin/service matahari-pm stop >/dev/null 2>&1 || :
- chkconfig --del matahari-pm
+fi
+%postun pm +if [ "$1" -ge "1" ]; then
- /sbin/service matahari-pm condrestart >/dev/null 2>&1 || :
+fi
#== Network
%post network @@ -297,6 +324,7 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot} %defattr(644, root, root, 755) %{_libdir}/libmcommon.so.* %{_libdir}/libmhost.so.* +%{_libdir}/libmpm.so.* %{_libdir}/libmnetwork.so.* %{_libdir}/libmservice.so.* %{_libdir}/libmconfig.so.* @@ -328,6 +356,19 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot} %attr(755, root, root) %{_sbindir}/matahari-dbus-hostd %endif
+%files pm +%defattr(644, root, root, 755) +%doc AUTHORS COPYING
+%if %{with qmf} +%attr(755, root, root) %{_initddir}/matahari-pm +%attr(755, root, root) %{_sbindir}/matahari-qmf-pmd +%endif
+%if %{with dbus} +%attr(755, root, root) %{_sbindir}/matahari-dbus-pmd +%endif
%files service %defattr(644, root, root, 755) %doc AUTHORS COPYING @@ -372,15 +413,19 @@ test "x%{buildroot}" != "x" && rm -rf %{buildroot} %if %{with dbus} %files dbus %{_sysconfdir}/dbus-1/system.d/org.matahariproject.Host.conf +%{_sysconfdir}/dbus-1/system.d/org.matahariproject.PM.conf %{_sysconfdir}/dbus-1/system.d/org.matahariproject.Network.conf %{_sysconfdir}/dbus-1/system.d/org.matahariproject.Services.conf %{_datadir}/dbus-1/interfaces/org.matahariproject.Host.xml +%{_datadir}/dbus-1/interfaces/org.matahariproject.PM.xml %{_datadir}/dbus-1/interfaces/org.matahariproject.Network.xml %{_datadir}/dbus-1/interfaces/org.matahariproject.Services.xml %{_datadir}/dbus-1/system-services/org.matahariproject.Host.service +%{_datadir}/dbus-1/system-services/org.matahariproject.PM.service %{_datadir}/dbus-1/system-services/org.matahariproject.Network.service %{_datadir}/dbus-1/system-services/org.matahariproject.Services.service %{_datadir}/polkit-1/actions/org.matahariproject.Host.policy +%{_datadir}/polkit-1/actions/org.matahariproject.PM.policy %{_datadir}/polkit-1/actions/org.matahariproject.Network.policy %{_datadir}/polkit-1/actions/org.matahariproject.Services.policy %endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5dda02d..7013e1e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,6 +132,7 @@ endif(WITH-QMF) ### Subdirectories add_subdirectory(lib) add_subdirectory(host) +add_subdirectory(pm) add_subdirectory(network) add_subdirectory(service) add_subdirectory(config) diff --git a/src/include/matahari/pm.h b/src/include/matahari/pm.h new file mode 100644 index 0000000..581dcda --- /dev/null +++ b/src/include/matahari/pm.h @@ -0,0 +1,70 @@ +/* ph.h - Copyright (C) 2011 Red Hat, Inc.
- Written by Jaroslav Škarvada jskarvad@redhat.com
- Based on code from Arjun Roy arroy@redhat.com
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+/**
- \file
- \brief PM API
- \ingroup coreapi
- */
+#ifndef __MH_PM_H__ +#define __MH_PM_H__
+#include <stdint.h> +#include <stdlib.h>
+#define TIMEOUT 10 +#define TA_PATH "/usr/bin/" +#define TA_SETPROFILE "profile" +#define TA_GETPROFILE "active" +#define TA_LISTPROFILES "list" +#define TA_OFF "off" +#define TUNEDADM TA_PATH "tuned-adm"
+#define SYSTEM32 "system32" +#define POWERCFG "powercfg" +#define PC_SETPROFILE "-SETACTIVE" +#define PC_GETPROFILE "-GETACTIVESCHEME" +#define PC_LISTPROFILES "-LIST"
+#define STR_UNK "UNKNOWN" +#define STR_ERR "ERROR"
+enum exec_exitcode {
- EC_OK = 0,
- EC_UNKNOWN_ERROR = 1,
- EC_INVALID_PARAM = 2,
- EC_UNIMPLEMENT_FEATURE = 3,
- EC_INSUFFICIENT_PRIV = 4,
- EC_NOT_INSTALLED = 5,
- /* 150-199<>reserved for application use */
- EC_SIGNAL = 194,
- EC_NOT_SUPPORTED = 195,
- EC_PENDING = 196,
- EC_CANCELLED = 197,
- EC_TIMEOUT = 198,
- EC_OTHER_ERROR = 199, /* Keep the same codes as LSB */
+};
+extern gboolean mh_pm_set_profile(const char *profile); +extern char *mh_pm_get_profile(void); +extern GList *mh_pm_list_profiles(void);
+#endif // __MH_PM_H__ diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index ab21bba..2f71375 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,6 +1,6 @@ # Library
-set(LIBS mcommon mhost mnetwork mservice mconfig) +set(LIBS mcommon mhost mnetwork mpm mservice mconfig) include_directories(${pcre_INCLUDE_DIRS})
# See http://sourceware.org/autobook/autobook/autobook_91.html for @@ -18,6 +18,10 @@ add_library (mnetwork SHARED network.c network_${VARIANT}.c) set_target_properties(mnetwork PROPERTIES SOVERSION 1.0.0) target_link_libraries(mnetwork ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
+add_library (mpm SHARED pm.c pm_${VARIANT}.c) +set_target_properties(mpm PROPERTIES SOVERSION 1.0.0) +target_link_libraries(mpm ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES})
add_library (mservice SHARED services.c services_${VARIANT}.c) set_target_properties(mservice PROPERTIES SOVERSION 1.0.0) target_link_libraries(mservice ${pcre_LIBRARIES} mcommon ${SIGAR} ${glib_LIBRARIES}) @@ -36,8 +40,8 @@ else(WIN32) install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX}) endforeach (lib ${LIBS}) # libresolv
- add_library(mcommon_resolv SHARED dnssrv_linux.c)
- target_link_libraries(mcommon mcommon_resolv resolv)
+# add_library(mcommon_resolv SHARED dnssrv_linux.c) +# target_link_libraries(mcommon mcommon_resolv resolv) endif(WIN32)
if(WITH-QMF) diff --git a/src/lib/pm.c b/src/lib/pm.c new file mode 100644 index 0000000..3d682cc --- /dev/null +++ b/src/lib/pm.c @@ -0,0 +1,45 @@ +/* pm.c - Copyright (C) 2011 Red Hat, Inc.
- Written by Jaroslav Škarvada andrew@beekhof.net
- Based on code from Andrew Beekhof andrew@beekhof.net
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+#ifndef WIN32 +#include "config.h" +#endif
+#include <stdio.h> +#include <glib.h> +#include "matahari/pm.h" +#include "matahari/logging.h" +#include "pm_private.h"
+MH_TRACE_INIT_DATA(mh_pm);
+gboolean mh_pm_set_profile(const char* profile) +{
- return pm_set_profile(profile);
The standard we're trying to use for OS-specific functions is to put "_os" after the api name. Eg.
pm_os_set_profile(...);
+}
+char *mh_pm_get_profile(void) +{
- return pm_get_profile();
+}
+GList *mh_pm_list_profiles(void) +{
- return pm_list_profiles();
+} diff --git a/src/lib/pm_linux.c b/src/lib/pm_linux.c new file mode 100644 index 0000000..37841a9 --- /dev/null +++ b/src/lib/pm_linux.c @@ -0,0 +1,259 @@ +/* pm_linux.c - Copyright (C) 2011 Red Hat, Inc.
- Written by Jaroslav Škarvada jskarvad@redhat.com
- Based on code from Andrew Beekhof andrew@beekhof.net
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+#include "config.h"
+#include <glib.h> +#include <stdio.h> +#include <unistd.h> +#include <signal.h> +#include <errno.h> +#include <sys/wait.h> +#include <sigar.h>
+#include "matahari/logging.h" +#include "matahari/pm.h" +#include "host_private.h"
+#define BUFSIZE 4096
+static void read_output(int fd, char **data)
This (and exec_command) is the same as the equivalent code in the services library right? It would be better to move it to a common location and use it from there.
Other than that, things look pretty good.
+{
- int bytes = 0, len = 0;
- char buf[BUFSIZE];
- while ((((bytes = read(fd, buf, BUFSIZE - 1)) > 0) &&
- (*data = realloc(*data, len + bytes + 1))) ||
- errno == EINTR)
- if (bytes > 0)
- {
- buf[bytes] = 0;
- mh_info("Read %d: %.*s", len, bytes, buf);
- sprintf(*data + len, "%s", buf);
- len += bytes;
- }
- mh_info("Read %d bytes", len);
+}
+static int exec_command(const char *apath, char *args[], int atimeout,
- char **stdoutbuf, char **stderrbuf)
+{
- int rc = EC_OK;
- GPid pid = 0;
- GError *gerr = NULL;
- int status = 0;
- int timeout = atimeout;
- gint stdout_fd;
- gint stderr_fd;
- if (!args || !args[0])
- return EC_OTHER_ERROR;
- mh_trace("Spawning '%s'\n", args[0]);
- if (!g_spawn_async_with_pipes(apath, args, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, &pid, NULL, &stdout_fd, &stderr_fd, &gerr))
- {
- mh_perror(LOG_ERR, "Spawn_process failed with code %d, message: %s\n",
- gerr->code, gerr->message);
- return EC_OTHER_ERROR;
- }
- mh_trace("Waiting for %d", pid);
- while (timeout > 0 && waitpid(pid, &status, WNOHANG) <= 0) {
- sleep(1);
- timeout--;
- }
- if (timeout == 0) {
- int killrc = sigar_proc_kill(pid, SIGKILL);
- rc = EC_TIMEOUT;
- mh_warn("%d - timed out after %dms", pid, atimeout);
- if (killrc != SIGAR_OK && killrc != ESRCH) {
- mh_err("kill(%d, KILL) failed: %d", pid, killrc);
- }
- } else if (WIFEXITED(status)) {
- rc = WEXITSTATUS(status);
- mh_err("Managed process %d exited with rc=%d", pid, rc);
- } else if (WIFSIGNALED(status)) {
- int signo = WTERMSIG(status);
- rc = EC_SIGNAL;
- mh_err("Managed process %d exited with signal=%d", pid, signo);
- }
- mh_trace("Child done: %d", pid);
- read_output(stdout_fd, stdoutbuf);
- read_output(stderr_fd, stderrbuf);
- if (*stdoutbuf)
- mh_debug("stdout: %s", *stdoutbuf);
- if (*stderrbuf)
- mh_debug("stderr: %s", *stderrbuf);
- close(stdout_fd);
- close(stderr_fd);
- g_spawn_close_pid(pid);
- return rc;
+}
+GList *pm_list_profiles(void) +{
- char *stdoutbuf = NULL;
- char *stderrbuf = NULL;
- char *c1, *c2;
- char *args[3] = {0};
- int cnt = 0;
- GList *list = NULL;
- args[0] = TUNEDADM;
- args[1] = TA_LISTPROFILES;
- args[2] = NULL;
- if (exec_command(NULL, args, TIMEOUT, &stdoutbuf, &stderrbuf) == EC_OK &&
- stdoutbuf)
- {
- c1 = stdoutbuf;
- do
- {
- if (*c1 == '-')
- {
- c2 = strchr(c1++, '\n');
- if (c2 > c1)
- {
- *c2 = 0;
- list = g_list_append(list, strdup(++c1));
- *c2 = '\n';
- cnt++;
- }
- }
- c2 = strchr(c1, '\n');
- if (c2)
- c1 = ++c2;
- }
- while (c2 && c1 - stdoutbuf < strlen(stdoutbuf));
- if (cnt)
- list = g_list_append(list, strdup(TA_OFF));
- }
- free(stdoutbuf);
- free(stderrbuf);
- return list;
+}
+static gboolean check_profile(const char *profile) +{
- GList *list = NULL;
- GList *llist;
- gboolean rc = FALSE;
- if (!(list = pm_list_profiles()))
- return FALSE;
- if (! g_list_length(list))
- return FALSE;
- for (llist = g_list_first(list); llist && !rc; llist = g_list_next(llist))
- {
- mh_trace("comparing '%s' with '%s'", (char *)llist->data, profile);
- if (! strcmp(profile, (char *)llist->data))
- rc = TRUE;
- }
- g_list_free_full(list, free);
- return rc;
+}
+gboolean pm_set_profile(const char *profile) +{
- char *stdoutbuf = NULL;
- char *stderrbuf = NULL;
- char *args[4] = {0};
- gboolean rc;
- args[0] = TUNEDADM;
- if (! profile)
- return FALSE;
- if (! strcmp(profile, TA_OFF)) {
- args[1] = TA_OFF;
- mh_trace("switching tuning off");
- }
- else
- {
- if (! check_profile(profile)) {
- mh_err("invalid profile: %s", profile);
- return FALSE;
- }
- args[1] = TA_SETPROFILE;
- mh_trace("setting profile: %s", profile);
- }
- args[2] = (char *)profile;
- args[3] = NULL;
- rc = exec_command(NULL, args, TIMEOUT, &stdoutbuf, &stderrbuf) == EC_OK;
- free(stdoutbuf);
- free(stderrbuf);
- return rc;
+}
+char *pm_get_profile(void) +{
- char *stdoutbuf = NULL;
- char *stderrbuf = NULL;
- char *rbuf = NULL;
- char *c1, *c2;
- char *args[3] = {0};
- args[0] = TUNEDADM;
- args[1] = TA_GETPROFILE;
- args[2] = NULL;
- if (exec_command(NULL, args, TIMEOUT, &stdoutbuf, &stderrbuf) == EC_OK)
- {
- if (stdoutbuf && strlen(stdoutbuf) && (c1 = strchr(stdoutbuf, ':')) &&
- (++c1 - stdoutbuf < strlen(stdoutbuf)))
- {
- if ((c2 = strchr(stdoutbuf, '\n')))
- *c2 = 0;
- rbuf = strdup(c1);
- }
- else
- rbuf = strdup(STR_UNK);
- }
- else
- rbuf = strdup(STR_ERR);
- free(stdoutbuf);
- free(stderrbuf);
- return rbuf;
+} diff --git a/src/lib/pm_private.h b/src/lib/pm_private.h new file mode 100644 index 0000000..b9532bc --- /dev/null +++ b/src/lib/pm_private.h @@ -0,0 +1,39 @@ +/* pm_private.h - Copyright (C) 2011 Red Hat, Inc.
- Written by Jaroslav Škarvada jskarvad@redhat.com
- Based on code from Darryl L. Pierce dpierce@redhat.com
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+/**
- \file
- \brief Platform specific function prototypes.
- The functions in this header must be implemented by the platform
- specific pm data code.
- - pm_linux.c
- - pm_windows.c
- */
+#ifndef __MH_PM_PRIVATE_H__ +#define __MH_PM_PRIVATE_H__
+#include <glib.h>
+extern gboolean pm_set_profile(const char *profile); +extern char *pm_get_profile(void); +extern GList *pm_list_profiles(void);
+#endif /* __MH_PM_PRIVATE_H__ */ diff --git a/src/lib/pm_windows.c b/src/lib/pm_windows.c new file mode 100644 index 0000000..f251886 --- /dev/null +++ b/src/lib/pm_windows.c @@ -0,0 +1,241 @@ +/* pm_windows.c - Copyright (C) 2011 Red Hat, Inc.
- Written by Jaroslav Škarvada jskarvad@redhat.com
- Based on code from Andrew Beekhof andrew@beekhof.net
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+/* Some code adapted from http://msdn.microsoft.com/en-us/library/ms682499(v=vs.85).aspx */
+#include <winsock.h> +#include <windows.h> +#include <winbase.h>
+#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <glib.h> +#include <io.h>
+#include "matahari/logging.h" +#include "matahari/pm.h" +#include "host_private.h"
+#define BUFSIZE 4096
+static void read_output(gint h, char **data) +{
- int len = 0;
- int bytes = 0;
- char buf[BUFSIZE];
- while ((bytes = _read(h, buf, BUFSIZE - 1)) > 0 &&
- (*data = realloc(*data, len + bytes + 1)))
- {
- buf[bytes] = 0;
- mh_info("Read %d: %.*s", len, bytes, buf);
- sprintf(*data + len, "%s", buf);
- len += bytes;
- }
- mh_info("Read %d bytes", len);
+}
+static +int exec_command(const char *apath, char *args[], int atimeout,
- char **stdoutbuf, char **stderrbuf)
+{
- DWORD status = 0;
- gint stdout_fd;
- gint stderr_fd;
- HANDLE phandle = NULL;
- GError *gerr = NULL;
- if (!args || !args[0])
- return EC_OTHER_ERROR;
- /* convert to ms */
- atimeout = atimeout * 1000;
- mh_trace("Spawning '%s'\n", args[0]);
- if (!g_spawn_async_with_pipes(apath, args, NULL,
- G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, (GPid *) &phandle, NULL,
- &stdout_fd, &stderr_fd, &gerr))
- {
- mh_perror(LOG_ERR, "Spawn_process failed with code %d, message: %s\n",
- gerr->code, gerr->message);
- return EC_OTHER_ERROR;
- }
- mh_trace("Waiting for %p", (void *)phandle);
- WaitForSingleObject(phandle, atimeout);
- if (GetExitCodeProcess(phandle, &status) == 0) {
- mh_err("Could not get exit code: %lu", GetLastError());
- status = EC_PENDING;
- }
- if (status == EC_PENDING) {
- status = EC_TIMEOUT;
- TerminateProcess(phandle, 1);
- mh_err("%p - timed out after %dms", (void *)phandle, atimeout);
- }
- /* Nice to log it somewhere */
- mh_debug("Result of '%s' was %d", args[0], (int)status);
- mh_trace("Child done: %p", (void *)phandle);
- read_output(stdout_fd, stdoutbuf);
- read_output(stderr_fd, stderrbuf);
- if (*stdoutbuf)
- mh_debug("stdout: %s", *stdoutbuf);
- if (*stderrbuf)
- mh_debug("stderr: %s", *stderrbuf);
- _close(stdout_fd);
- _close(stderr_fd);
- g_spawn_close_pid((GPid *)phandle);
- return (int) status;
+}
+static +gboolean get_profiles(GList **names, GList **guids) +{
- gboolean rc = FALSE;
- int len;
- char *stdoutbuf = NULL;
- char *stderrbuf = NULL;
- char *c1, *c2;
- char *args[3] = {0};
- args[0] = SYSTEM32 "\" POWERCFG;
- args[1] = PC_LISTPROFILES;
- args[2] = NULL;
- if (exec_command(getenv("WINDIR"), args , TIMEOUT, &stdoutbuf, &stderrbuf) == EC_OK &&
- stdoutbuf)
- {
- rc = TRUE;
- len = strlen(stdoutbuf);
- c1 = stdoutbuf;
- while ((c1 = strstr(c1, "GUID: ")))
- {
- c1 += 6;
- if (c1 - stdoutbuf < len && (c2 = strchr(c1, ' ')))
- {
- *c2++ = 0;
- *guids = g_list_append(*guids, strdup(c1));
- if ((c1 = strchr(c2, '(')) && ++c1 - stdoutbuf < len &&
- (c2 = strchr(c1, ')')))
- {
- *c2 = 0;
- *names = g_list_append(*names, strdup(c1));
- *c2 = ')';
- }
- }
- }
- }
- if (!*names || !*guids || g_list_length(*names) != g_list_length(*guids))
- rc = FALSE;
- free(stdoutbuf);
- free(stderrbuf);
- return rc;
+}
+gboolean pm_set_profile(const char *profile) +{
- gboolean rc = FALSE;
- char *guid = NULL;
- char *stdoutbuf = NULL;
- char *stderrbuf = NULL;
- GList *names = NULL;
- GList *guids = NULL;
- GList *pnames = NULL;
- GList *pguids = NULL;
- char *args[4] = {0};
- if (! get_profiles(&names, &guids))
- return FALSE;
- for (pnames = g_list_first(names), pguids = g_list_first(guids);
- pnames && pguids && !guid;
- pnames = g_list_next(pnames), pguids = g_list_next(pguids))
- if (!strcmp((char *)pnames->data, profile))
- guid = strdup((char *)pguids->data);
- g_list_free_full(names, free);
- g_list_free_full(guids, free);
- if (guid)
- {
- args[0] = SYSTEM32 "\" POWERCFG;
- args[1] = PC_SETPROFILE;
- args[2] = guid;
- args[3] = NULL;
- rc = exec_command(getenv("WINDIR"), args, TIMEOUT,
- &stdoutbuf, &stderrbuf) == EC_OK;
- free(guid);
- free(stdoutbuf);
- free(stderrbuf);
- }
- return rc;
+}
+char *pm_get_profile(void) +{
- char *rbuf = NULL;
- char *stdoutbuf = NULL;
- char *stderrbuf = NULL;
- char *c1, *c2;
- char *args[3] = {0};
- args[0] = SYSTEM32 "\" POWERCFG;
- args[1] = PC_GETPROFILE;
- args[2] = NULL;
- if (exec_command(getenv("WINDIR"), args, TIMEOUT,
- &stdoutbuf, &stderrbuf) == EC_OK && stdoutbuf &&
- (c1 = strchr(stdoutbuf, '(')) && ++c1 - stdoutbuf < strlen(stdoutbuf) &&
- (c2 = strchr(c1, ')')))
- {
- *c2 = 0;
- rbuf = strdup(c1);
- }
- else rbuf = strdup(STR_ERR);
- free(stdoutbuf);
- free(stderrbuf);
- return rbuf;
+}
+GList *pm_list_profiles(void) +{
- GList *names = NULL;
- GList *guids = NULL;
- get_profiles(&names, &guids);
- g_list_free_full(guids, free);
- return names;
+} diff --git a/src/pm/CMakeLists.txt b/src/pm/CMakeLists.txt new file mode 100644 index 0000000..512f3f4 --- /dev/null +++ b/src/pm/CMakeLists.txt @@ -0,0 +1,61 @@ +set(BASE "pm") +set(BASE_LIB "m${BASE}") +set(QMF_AGENT "matahari-qmf-${BASE}d") +set(DBUS_AGENT "matahari-dbus-${BASE}d")
+# QMF daemon +if(WITH-QMF)
- set(SCHEMA_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/qmf/org/matahariproject/QmfPackage.cpp)
- generate_qmf_schemas(${CMAKE_CURRENT_SOURCE_DIR}/schema.xml ${SCHEMA_SOURCES})
- include_directories(${CMAKE_CURRENT_BINARY_DIR})
- add_executable(${QMF_AGENT} ${BASE}-qmf.cpp ${SCHEMA_SOURCES})
- target_link_libraries(${QMF_AGENT} ${BASE_LIB} mcommon mcommon_qmf)
- target_link_libraries(${QMF_AGENT} ${QPIDCOMMON_LIBRARY} ${QPIDCLIENT_LIBRARY} ${QPIDMESSAGING_LIBRARY} ${QMF2_LIBRARY})
- if(QPIDTYPES_LIBRARY)
- target_link_libraries(${QMF_AGENT} ${QPIDTYPES_LIBRARY})
- endif(QPIDTYPES_LIBRARY)
- if(WIN32)
- target_link_libraries(${QMF_AGENT} wsock32)
- endif(WIN32)
- if(NOT WIN32)
- configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
- endif(NOT WIN32)
- install(TARGETS ${QMF_AGENT} DESTINATION sbin)
+endif(WITH-QMF)
+# DBus daemon +if(WITH-DBUS)
- # Auto-generated stuff
- generate_dbus_headers(${BASE} ${CMAKE_CURRENT_BINARY_DIR}/org.matahariproject.PM.xml)
- # Create src/dbus directory and generate DBus XML definition files into it
- generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/schema.xml)
- # Must be included to find matahari-API-dbus-properties.h
- include_directories(${CMAKE_CURRENT_BINARY_DIR})
- set(DBUS_AGENT_SOURCE
- ${BASE}-dbus.c
- ${BASE}-dbus-glue.h
- ${BASE}-dbus-properties.h
- )
- add_executable(${DBUS_AGENT} ${DBUS_AGENT_SOURCE})
- target_link_libraries(${DBUS_AGENT} ${BASE_LIB} mcommon_dbus ${dbus-glib_LIBRARIES})
- include_directories(${dbus-glib_INCLUDE_DIRS})
- # Install targets
- # TODO: fix hardcoded paths, should go to libexec
- install(TARGETS ${DBUS_AGENT} DESTINATION sbin)
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.matahariproject.PM.xml DESTINATION share/dbus-1/interfaces)
- install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.service DESTINATION share/dbus-1/system-services)
- install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.conf DESTINATION /etc/dbus-1/system.d)
- install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.matahariproject.PM.policy DESTINATION share/polkit-1/actions)
+endif(WITH-DBUS) diff --git a/src/pm/org.matahariproject.PM.conf b/src/pm/org.matahariproject.PM.conf new file mode 100644 index 0000000..1afe8a8 --- /dev/null +++ b/src/pm/org.matahariproject.PM.conf @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE busconfig PUBLIC
- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd%22%3E
+<busconfig>
- <!-- Only root can own the service -->
- <policy user="root">
- <allow own="org.matahariproject.PM"/>
- </policy>
- <!-- Allow anyone to invoke methods on the interfaces -->
- <policy context="default">
- <allow send_destination="org.matahariproject.PM"/>
- </policy>
+</busconfig> diff --git a/src/pm/org.matahariproject.PM.policy b/src/pm/org.matahariproject.PM.policy new file mode 100644 index 0000000..eb2c617 --- /dev/null +++ b/src/pm/org.matahariproject.PM.policy @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> +<policyconfig>
- <vendor>Matahari</vendor>
- <vendor_url>https://fedorahosted.org/matahari/</vendor_url>
- <action id="org.matahariproject.PM.set_profile">
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>auth_admin</allow_active>
- </defaults>
- </action>
- <action id="org.matahariproject.PM.get_profile">
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>auth_admin</allow_active>
- </defaults>
- </action>
- <action id="org.matahariproject.PM.list_profiles">
- <defaults>
- <allow_any>no</allow_any>
- <allow_inactive>no</allow_inactive>
- <allow_active>auth_admin</allow_active>
- </defaults>
- </action>
+</policyconfig> diff --git a/src/pm/org.matahariproject.PM.service b/src/pm/org.matahariproject.PM.service new file mode 100644 index 0000000..f293a71 --- /dev/null +++ b/src/pm/org.matahariproject.PM.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.matahariproject.PM +Exec=/usr/sbin/matahari-dbus-pmd +User=root diff --git a/src/pm/pm-dbus.c b/src/pm/pm-dbus.c new file mode 100644 index 0000000..8fd325c --- /dev/null +++ b/src/pm/pm-dbus.c @@ -0,0 +1,142 @@ +/*
- matahari-pm-dbus.c
- Copyright (C) 2011 Red Hat, Inc.
- Written by Jaroslav Škarvada jskarvad@redhat.com
- Based on code from Roman Rakus rrakus@redhat.com,
- Radek Novacek rnovacek@redhat.com
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+#include <string.h>
+#include "matahari/mh_dbus_common.h" +#include "matahari/utilities.h"
+/* PM methods */ +#include "matahari/pm.h"
+/* Generated properties list */ +#include "pm-dbus-properties.h"
+/* DBus names */ +#define PM_BUS_NAME "org.matahariproject.PM" +#define PM_OBJECT_PATH "/org/matahariproject/PM" +#define PM_INTERFACE_NAME "org.matahariproject.PM" +#define DBUS_PROPERTY_INTERAFACE_NAME "org.freedesktop.DBus.Properties"
+/* Dbus methods */ +gboolean +PM_set_profile(Matahari* matahari, const char *profile, DBusGMethodInvocation *context) +{
- GError* error = NULL;
- if (!check_authorization(PM_BUS_NAME ".set_profile", &error, context)) {
- dbus_g_method_return_error(context, error);
- return FALSE;
- }
- dbus_g_method_return(context, mh_pm_set_profile(profile));
- return TRUE;
+}
+gboolean +PM_get_profile(Matahari* matahari, DBusGMethodInvocation *context) +{
- char *profile;
- GError* error = NULL;
- if (!check_authorization(PM_BUS_NAME ".get_profile", &error, context)) {
- dbus_g_method_return_error(context, error);
- return FALSE;
- }
- profile = mh_pm_get_profile();
- dbus_g_method_return(context, g_strdup(profile));
- free(profile);
- return TRUE;
+}
+gboolean +PM_list_profiles(Matahari* matahari, DBusGMethodInvocation *context) +{
- GError* error = NULL;
- GList *list;
- GList *plist;
- char **profiles;
- int i = 0;
- if (!check_authorization(PM_BUS_NAME ".list_profiles", &error, context)) {
- dbus_g_method_return_error(context, error);
- return FALSE;
- }
- list = mh_pm_list_profiles();
- profiles = g_new(char *, g_list_length(list) + 1);
- for (plist = g_list_first(list); plist; plist = g_list_next(plist))
- profiles[i++] = g_strdup((char *)plist->data);
- profiles[i] = NULL;
- dbus_g_method_return(context, profiles);
- g_strfreev(profiles);
- g_list_free_full(list, free);
- return TRUE;
+}
+/* Generated dbus stuff for pm
- MUST be after declaration of user defined functions.
- */
+#include "pm-dbus-glue.h"
+void +matahari_set_property(GObject *object, guint property_id, const GValue *value,
- GParamSpec *pspec)
+{
- switch (property_id) {
- default:
- /* We don't have any other property... */
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
+}
+void +matahari_get_property(GObject *object, guint property_id, GValue *value,
- GParamSpec *pspec)
+{
- switch (property_id) {
- case PROP_UUID:
- g_value_set_string(value, mh_uuid());
- break;
- case PROP_HOSTNAME:
- g_value_set_string(value, mh_hostname());
- break;
- default:
- /* We don't have any other property... */
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
+}
+GType +matahari_dict_type(int prop) +{
- g_printerr("Type of property %s is map of unknown types\n",
- properties[prop].name);
- return G_TYPE_VALUE;
+}
+int +main(int argc, char** argv) +{
- g_type_init();
- return run_dbus_server(PM_BUS_NAME, PM_OBJECT_PATH);
+} diff --git a/src/pm/pm-qmf.cpp b/src/pm/pm-qmf.cpp new file mode 100644 index 0000000..40084aa --- /dev/null +++ b/src/pm/pm-qmf.cpp @@ -0,0 +1,107 @@ +/* matahari-pm.cpp - Copyright (C) 2011 Red Hat, Inc.
- Written by Jaroslav Škarvada jskarvad@redhat.com
- Based on code from Roman Rakus rrakus@redhat.com,
- Radek Novacek rnovacek@redhat.com
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+#ifndef WIN32 +#include "config.h" +#endif
+#include "matahari/mh_agent.h" +#include <qmf/Data.h> +#include "qmf/org/matahariproject/QmfPackage.h"
+extern "C" { +#include <string.h> +#include "matahari/pm.h" +#include "matahari/logging.h" +#include "matahari/utilities.h" +}
+class PMAgent : public MatahariAgent +{ +private:
- qmf::org::matahariproject::PackageDefinition _package;
+public:
- virtual int setup(qmf::AgentSession session);
- virtual gboolean invoke(qmf::AgentSession session, qmf::AgentEvent event,
- gpointer user_data);
+};
+int +main(int argc, char **argv) +{
- PMAgent *agent = new PMAgent();
- int rc = agent->init(argc, argv, "pm");
- if (rc == 0) {
- agent->run();
- }
- return rc;
+}
+gboolean +PMAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event,
- gpointer user_data)
+{
- if (event.getType() != qmf::AGENT_METHOD)
- return TRUE;
- const std::string& methodName(event.getMethodName());
- if (methodName == "set_profile") {
- event.addReturnArgument("status",
- mh_pm_set_profile(event.getArguments()["profile"].asString().c_str()));
- } else if (methodName == "get_profile") {
- _qtype::Variant profile;
- char *pprofile = mh_pm_get_profile();
- profile = pprofile;
- free(pprofile);
- event.addReturnArgument("profile", profile);
- } else if (methodName == "list_profiles") {
- GList *plist = NULL;
- GList *profiles = mh_pm_list_profiles();
- _qtype::Variant::List s_list;
- for (plist = g_list_first(profiles); plist;
- plist = g_list_next(plist))
- s_list.push_back((char *)plist->data);
- g_list_free_full(profiles, free);
- event.addReturnArgument("profiles", s_list);
- } else {
- session.raiseException(event, MH_NOT_IMPLEMENTED);
- goto bail;
- }
- session.methodSuccess(event);
+bail:
- return TRUE;
+}
+int +PMAgent::setup(qmf::AgentSession session) +{
- _package.configure(session);
- _instance = qmf::Data(_package.data_PM);
- _instance.setProperty("hostname", mh_hostname());
- _instance.setProperty("uuid", mh_uuid());
- session.addData(_instance);
- return 0;
+} diff --git a/src/pm/schema.xml b/src/pm/schema.xml new file mode 100644 index 0000000..c2e580b --- /dev/null +++ b/src/pm/schema.xml @@ -0,0 +1,21 @@ +<schema package="org.matahariproject">
+<!-- PM API -->
- <class name="PM">
- <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
- <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
- <!-- APIs -->
- <method name="set_profile" desc="Set PM profile">
- <arg name="profile" dir="I" type="sstr" />
- <arg name="status" dir="O" type="uint32" />
- </method>
- <method name="get_profile" desc="Get current PM profile">
- <arg name="profile" dir="O" type="sstr" />
- </method>
- <method name="list_profiles" desc="List available PM profiles">
- <arg name="profiles" dir="O" type="list" />
- </method>
- </class>
+</schema> diff --git a/src/schema.xml b/src/schema.xml index d39c82d..1645bf4 100644 --- a/src/schema.xml +++ b/src/schema.xml @@ -58,6 +58,24 @@
<event name="heartbeat" args="timestamp,sequence" />
+<!-- PM API -->
- <class name="PM">
- <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
- <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
- <!-- APIs -->
- <method name="set_profile" desc="Set PM profile">
- <arg name="profile" dir="I" type="sstr" />
- <arg name="status" dir="O" type="uint32" />
- </method>
- <method name="get_profile" desc="Get current PM profile">
- <arg name="profile" dir="O" type="sstr" />
- </method>
- <method name="list_profiles" desc="List available PM profiles">
- <arg name="profiles" dir="O" type="list" />
- </method>
- </class>
<!-- Network API --> <class name="Network"> <property name="uuid" type="sstr" access="RO" desc="Host UUID" /> diff --git a/src/windows/install.bat b/src/windows/install.bat index 5e6307e..5a47775 100644 --- a/src/windows/install.bat +++ b/src/windows/install.bat @@ -12,7 +12,7 @@ cd "%target%"
rem Now install the agents as services and start them
-set agents=hostd networkd serviced +set agents=hostd pmd networkd serviced for %%A in (%agents%) do sc delete mh_%%A for %%A in (%agents%) do del mh_%%A.exe for %%A in (%agents%) do copy srvany.exe mh_%%A.exe -- 1.7.5.2
Matahari mailing list Matahari@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/matahari