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(a)redhat.com>
+ * Based on code from Arjun Roy <arroy(a)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(a)beekhof.net>
+ * Based on code from Andrew Beekhof <andrew(a)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);
+}
+
+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(a)redhat.com>
+ * Based on code from Andrew Beekhof <andrew(a)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)
+{
+ 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(a)redhat.com>
+ * Based on code from Darryl L. Pierce <dpierce(a)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(a)redhat.com>
+ * Based on code from Andrew Beekhof <andrew(a)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">
+<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(a)redhat.com>
+ * Based on code from Roman Rakus <rrakus(a)redhat.com>,
+ * Radek Novacek <rnovacek(a)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(a)redhat.com>
+ * Based on code from Roman Rakus <rrakus(a)redhat.com>,
+ * Radek Novacek <rnovacek(a)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