[PATCH] host: Add power management functionality v2
by Radek Novacek
Functions for listing, setting and getting power management profiles for
the host agent, including unittest. Based on patch by
Jaroslav Skarvada <jskarvad(a)redhat.com>
Signed-off-by: Radek Novacek <rnovacek(a)redhat.com>
---
matahari.spec.in | 2 +
src/host/host-dbus.c | 79 +++++++++++
src/host/host-qmf.cpp | 31 ++++
src/host/org.matahariproject.Host.policy | 21 +++
src/host/schema.xml | 13 ++
src/include/matahari/host.h | 35 +++++
src/include/matahari/utilities.h | 12 ++
src/lib/host.c | 18 +++
src/lib/host_linux.c | 223 ++++++++++++++++++++++++++++++
src/lib/host_private.h | 28 ++++
src/lib/host_windows.c | 205 +++++++++++++++++++++++++++
src/lib/utilities.c | 25 ++++
src/unittests/mh_api_host.h | 37 +++++
13 files changed, 729 insertions(+), 0 deletions(-)
diff --git a/matahari.spec.in b/matahari.spec.in
index 8f105f4..83301c7 100644
--- a/matahari.spec.in
+++ b/matahari.spec.in
@@ -168,6 +168,8 @@ Requires: dmidecode
Requires(post): chkconfig
Requires(preun):chkconfig
Requires(preun):initscripts
+# Power management functions in host agent require tuned
+Requires: tuned
%description host
QMF agent for viewing and controlling remote hosts
diff --git a/src/host/host-dbus.c b/src/host/host-dbus.c
index 05b25f3..9ef8b6c 100644
--- a/src/host/host-dbus.c
+++ b/src/host/host-dbus.c
@@ -119,6 +119,85 @@ Host_set_uuid(Matahari* matahari, const char *lifetime, const char *uuid, DBusGM
return TRUE;
}
+gboolean
+Host_set_power_profile(Matahari* matahari, const char *profile, DBusGMethodInvocation *context)
+{
+ GError *error = NULL;
+ enum mh_result res;
+
+ if (!check_authorization(HOST_BUS_NAME ".set_power_profile", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+ res = mh_host_set_power_profile(profile);
+ if (res != MH_RES_SUCCESS) {
+ error = g_error_new(MATAHARI_ERROR, res, mh_result_to_str(res));
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+
+ dbus_g_method_return(context, 0);
+ return TRUE;
+}
+
+gboolean
+Host_get_power_profile(Matahari* matahari, DBusGMethodInvocation *context)
+{
+ char *profile = NULL;
+ GError *error = NULL;
+ enum mh_result res;
+
+ if (!check_authorization(HOST_BUS_NAME ".get_power_profile", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+ res = mh_host_get_power_profile(&profile);
+ if (res != MH_RES_SUCCESS) {
+ error = g_error_new(MATAHARI_ERROR, res, mh_result_to_str(res));
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+ dbus_g_method_return(context, profile);
+ free(profile);
+ return TRUE;
+}
+
+gboolean
+Host_list_power_profiles(Matahari* matahari, DBusGMethodInvocation *context)
+{
+ GError *error = NULL;
+ GList *list, *plist;
+ char **profiles;
+ int i = 0;
+
+ if (!check_authorization(HOST_BUS_NAME ".list_power_profiles", &error, context)) {
+ dbus_g_method_return_error(context, error);
+ g_error_free(error);
+ return FALSE;
+ }
+ // Get the list of profiles
+ list = mh_host_list_power_profiles();
+
+ // Convert GList * with profiles to array (char **)
+ profiles = g_new(char *, g_list_length(list) + 1);
+ for (plist = g_list_first(list);
+ plist;
+ plist = g_list_next(plist)) {
+ profiles[i++] = plist->data;
+ }
+ profiles[i] = NULL; // Sentinel
+
+ dbus_g_method_return(context, profiles);
+ g_list_free_full(list, free);
+ g_free(profiles);
+ return TRUE;
+}
+
+
/* Generated dbus stuff for host
* MUST be after declaration of user defined functions.
*/
diff --git a/src/host/host-qmf.cpp b/src/host/host-qmf.cpp
index 618cf9c..4b72d00 100644
--- a/src/host/host-qmf.cpp
+++ b/src/host/host-qmf.cpp
@@ -112,6 +112,7 @@ HostAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event,
return TRUE;
}
+ enum mh_result res = MH_RES_SUCCESS;
const std::string& methodName(event.getMethodName());
qpid::types::Variant::Map& args = event.getArguments();
@@ -153,7 +154,37 @@ HostAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event,
if (uuid) {
event.addReturnArgument("uuid", uuid);
}
+ } else if (methodName == "set_power_profile") {
+ res = mh_host_set_power_profile(args["profile"].asString().c_str());
+ if (res != MH_RES_SUCCESS) {
+ session.raiseException(event, mh_result_to_str(res));
+ goto bail;
+ } else {
+ event.addReturnArgument("status", 0);
+ }
+ } else if (methodName == "get_power_profile") {
+ char *profile = NULL;
+ res = mh_host_get_power_profile(&profile);
+ if (res != MH_RES_SUCCESS) {
+ session.raiseException(event, mh_result_to_str(res));
+ goto bail;
+ } else {
+ event.addReturnArgument("profile", profile);
+ }
+ free(profile);
+ } else if (methodName == "list_power_profiles") {
+ GList *plist = NULL;
+ GList *profile_list = NULL;
+ _qtype::Variant::List s_list;
+
+ profile_list = mh_host_list_power_profiles();
+ for (plist = g_list_first(profile_list); plist;
+ plist = g_list_next(plist)) {
+ s_list.push_back((const char *) plist->data);
+ }
+ event.addReturnArgument("profiles", s_list);
+ g_list_free_full(profile_list, free);
} else {
session.raiseException(event, mh_result_to_str(MH_RES_NOT_IMPLEMENTED));
goto bail;
diff --git a/src/host/org.matahariproject.Host.policy b/src/host/org.matahariproject.Host.policy
index ed04a25..90636a8 100644
--- a/src/host/org.matahariproject.Host.policy
+++ b/src/host/org.matahariproject.Host.policy
@@ -200,4 +200,25 @@
<allow_active>auth_admin</allow_active>
</defaults>
</action>
+ <action id="org.matahariproject.Host.get_power_profile">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+ <action id="org.matahariproject.Host.set_power_profile">
+ <defaults>
+ <allow_any>no</allow_any>
+ <allow_inactive>no</allow_inactive>
+ <allow_active>auth_admin</allow_active>
+ </defaults>
+ </action>
+ <action id="org.matahariproject.Host.list_power_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/host/schema.xml b/src/host/schema.xml
index 1841907..f5b2092 100644
--- a/src/host/schema.xml
+++ b/src/host/schema.xml
@@ -90,6 +90,19 @@
<arg name="uuid" dir="I" type="sstr" />
<arg name="rc" dir="O" type="int32" />
</method>
+
+ <method name="set_power_profile" desc="Set power management profile">
+ <arg name="profile" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+
+ <method name="get_power_profile" desc="Get current power management profile">
+ <arg name="profile" dir="O" type="sstr" />
+ </method>
+
+ <method name="list_power_profiles" desc="List available power management profiles">
+ <arg name="profiles" dir="O" type="list" />
+ </method>
</class>
<event name="heartbeat" args="timestamp,sequence,hostname,uuid" />
diff --git a/src/include/matahari/host.h b/src/include/matahari/host.h
index 1da756a..31a5a98 100644
--- a/src/include/matahari/host.h
+++ b/src/include/matahari/host.h
@@ -28,6 +28,9 @@
#include <stdint.h>
#include <stdlib.h>
#include <sigar.h>
+#include <glib.h>
+
+#include "matahari/errors.h"
/**
* Get a UUID for a host.
@@ -118,4 +121,36 @@ mh_host_get_load_averages(sigar_loadavg_t *avg);
void
mh_host_get_processes(sigar_proc_stat_t *procs);
+/**
+ * Set power management profile.
+ *
+ * \param[in] profile One of profile returned by mh_host_list_power_profiles
+ * function
+ * \return see enum mh_result
+ */
+enum mh_result
+mh_host_set_power_profile(const char *profile);
+
+/**
+ * Get current power management profile.
+ *
+ * \param[out] profile Variable where current profile will be written to.
+ * Variable must be freed with free().
+ *
+ * \return see enum mh_result
+ */
+enum mh_result
+mh_host_get_power_profile(char **profile);
+
+/**
+ * Get list of all available power management profiles.
+ *
+ * \note The return of this routine must be freed with
+ * g_list_free_full(returned_list, free);
+ *
+ * \return list of all profiles.
+ */
+GList *
+mh_host_list_power_profiles(void);
+
#endif // __MH_HOST_H__
diff --git a/src/include/matahari/utilities.h b/src/include/matahari/utilities.h
index 893d068..5084261 100644
--- a/src/include/matahari/utilities.h
+++ b/src/include/matahari/utilities.h
@@ -128,4 +128,16 @@ mh_strlen_zero(const char *s)
char *
mh_string_copy(char *dst, const char *src, size_t dst_len);
+/**
+ * Read the whole content of file from file descriptor
+ *
+ * \param[in] fd File descriptor to read from. Must be readable.
+ * \param[out] data Data read from the file. Must be freed with free().
+ *
+ * \retval 0 File is empty
+ * \retval >0 Number of characters read
+ * \retval <0 Error occured
+ */
+gsize
+mh_read_from_fd(int fd, char **data);
#endif
diff --git a/src/lib/host.c b/src/lib/host.c
index eb712c9..c6fb4c8 100644
--- a/src/lib/host.c
+++ b/src/lib/host.c
@@ -310,3 +310,21 @@ mh_host_set_uuid(const char *lifetime, const char *uuid)
return G_FILE_ERROR_NOSYS;
}
+
+enum mh_result
+mh_host_set_power_profile(const char* profile)
+{
+ return host_os_set_power_profile(profile);
+}
+
+enum mh_result
+mh_host_get_power_profile(char **profile)
+{
+ return host_os_get_power_profile(profile);
+}
+
+GList *
+mh_host_list_power_profiles(void)
+{
+ return host_os_list_power_profiles();
+}
diff --git a/src/lib/host_linux.c b/src/lib/host_linux.c
index 5b9a4f9..ac9c305 100644
--- a/src/lib/host_linux.c
+++ b/src/lib/host_linux.c
@@ -24,10 +24,12 @@
#include <limits.h>
#include <string.h>
#include <fcntl.h>
+#include <errno.h>
#include <sys/reboot.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#include <sys/ioctl.h>
+#include <sys/wait.h>
#include <linux/reboot.h>
#include <linux/kd.h>
@@ -45,6 +47,7 @@
#define UUID_STR_BUF_LEN 37
+#define BUFSIZE 4096
const char *
host_os_get_cpu_flags(void)
@@ -436,3 +439,223 @@ host_os_set_custom_uuid(const char *uuid)
return rc;
}
+static enum mh_result
+exec_command(const char *apath, char *args[], int atimeout, char **stdoutbuf,
+ char **stderrbuf)
+{
+ enum mh_result res = MH_RES_SUCCESS;
+ GPid pid = 0;
+ GError *gerr = NULL;
+ int status = 0;
+ int timeout = atimeout;
+ gint stdout_fd;
+ gint stderr_fd;
+
+ if (!args || !args[0])
+ return MH_RES_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 MH_RES_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);
+
+ res = MH_RES_BACKEND_ERROR;
+ 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)) {
+ if (WEXITSTATUS(status) > 0)
+ res = MH_RES_BACKEND_ERROR;
+ mh_err("Managed process %d exited with rc=%d", pid, WEXITSTATUS(status));
+
+ } else if (WIFSIGNALED(status)) {
+ int signo = WTERMSIG(status);
+ res = MH_RES_BACKEND_ERROR;
+ mh_err("Managed process %d exited with signal=%d", pid, signo);
+ }
+
+ mh_trace("Child done: %d", pid);
+
+ if (stdoutbuf) {
+ if (mh_read_from_fd(stdout_fd, stdoutbuf) < 0) {
+ mh_err("Unable to read standard output from command %s.", apath);
+ stdoutbuf = NULL;
+ } else {
+ mh_debug("stdout: %s", *stdoutbuf);
+ }
+ }
+
+ if (stderrbuf) {
+ if (mh_read_from_fd(stderr_fd, stderrbuf) < 0) {
+ mh_err("Unable to read standard error output from command %s.", apath);
+ stderrbuf = NULL;
+ } else {
+ mh_debug("stderr: %s", *stderrbuf);
+ }
+ }
+
+ close(stdout_fd);
+ close(stderr_fd);
+
+ g_spawn_close_pid(pid);
+
+ return res;
+}
+
+GList *
+host_os_list_power_profiles(void)
+{
+ char *stdoutbuf = NULL;
+ char *c1, *c2;
+ char *args[3] = {0};
+ GList *list = NULL;
+ enum mh_result res;
+ int len;
+
+ args[0] = TUNEDADM;
+ args[1] = TA_LISTPROFILES;
+ args[2] = NULL;
+
+ res = exec_command(NULL, args, TIMEOUT, &stdoutbuf, NULL);
+ len = strlen(stdoutbuf);
+
+ if (res == MH_RES_SUCCESS && stdoutbuf) {
+ c1 = stdoutbuf;
+ do {
+ // Each line with profile in "tuned-adm list" starts with "-"
+ if (*c1 == '-' && c1 - stdoutbuf + 2 < len) {
+ // Skip the dash and the space after it
+ c1 += 2;
+ // Profile name is the rest of the line
+ c2 = strchr(c1, '\n');
+ if (c2 && c2 > c1) {
+ // Replace \n with \0 and append it to output
+ *c2 = '\0';
+ list = g_list_append(list, strdup(c1));
+ // Replace it back with \n, so free() will free whole string
+ *c2 = '\n';
+ }
+ } else {
+ // Line doesn't contain the profile -> skip the line
+ c2 = strchr(c1, '\n');
+ }
+ // Move c1 to beggining of the next line
+ if (c2) {
+ c1 = c2 + 1;
+ }
+ } while (c2 && c1 - stdoutbuf < len);
+
+ if (g_list_length(list) == 0) {
+ // Return at least "off" profile, if no other profile found
+ list = g_list_append(list, strdup(TA_OFF));
+ }
+ }
+ free(stdoutbuf);
+
+ return list;
+}
+
+static gboolean
+check_profile(const char *profile)
+{
+ GList *list = NULL;
+ GList *llist;
+ gboolean rc = FALSE;
+
+ if (!(list = host_os_list_power_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;
+ break;
+ }
+ }
+ g_list_free_full(list, free);
+
+ return rc;
+}
+
+enum mh_result
+host_os_set_power_profile(const char *profile)
+{
+ char *args[4] = {0};
+
+ args[0] = TUNEDADM;
+ if (!profile)
+ return MH_RES_INVALID_ARGS;
+
+ 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 MH_RES_INVALID_ARGS;
+ }
+ args[1] = TA_SETPROFILE;
+ mh_trace("setting profile: %s", profile);
+ }
+
+ args[2] = (char *) profile;
+ args[3] = NULL;
+
+ return exec_command(NULL, args, TIMEOUT, NULL, NULL);
+}
+
+enum mh_result
+host_os_get_power_profile(char **profile)
+{
+ char *stdoutbuf = NULL;
+ char *c1, *c2 = NULL;
+ char *args[3] = {0};
+ enum mh_result res;
+
+ args[0] = TUNEDADM;
+ args[1] = TA_GETPROFILE;
+ args[2] = NULL;
+
+ res = exec_command(NULL, args, TIMEOUT, &stdoutbuf, NULL);
+ if (res == MH_RES_SUCCESS) {
+ // Parse first line of "tuned-adm active", that is something like
+ // "Current active profile: profile_name", so take what is after
+ // semicolon and space to the end of the line
+ if (stdoutbuf && (c1 = strchr(stdoutbuf, ':')) &&
+ (c1 - stdoutbuf + 2 < strlen(stdoutbuf))) {
+ if ((c2 = strchr(c1, '\n'))) {
+ *c2 = '\0';
+ }
+ // + 2 because we need to skip semicolon and space
+ *profile = strdup(c1 + 2);
+ if (c2)
+ *c2 = '\n';
+ } else {
+ *profile = strdup(STR_UNK);
+ }
+ } else {
+ res = MH_RES_BACKEND_ERROR;
+ }
+ free(stdoutbuf);
+
+ return res;
+}
diff --git a/src/lib/host_private.h b/src/lib/host_private.h
index c2f7a1b..3a985d5 100644
--- a/src/lib/host_private.h
+++ b/src/lib/host_private.h
@@ -31,6 +31,25 @@
#include <glib.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 GUID "GUID: "
+
+#define STR_UNK "UNKNOWN"
+#define STR_ERR "ERROR"
+
+
const char *
host_os_get_cpu_flags(void);
@@ -67,4 +86,13 @@ host_os_agent_uuid(void);
int
host_os_set_custom_uuid(const char *uuid);
+enum mh_result
+host_os_set_power_profile(const char *profile);
+
+enum mh_result
+host_os_get_power_profile(char **profile);
+
+GList *
+host_os_list_power_profiles(void);
+
#endif /* __MH_HOST_PRIVATE_H__ */
diff --git a/src/lib/host_windows.c b/src/lib/host_windows.c
index f53567c..fb8af0b 100644
--- a/src/lib/host_windows.c
+++ b/src/lib/host_windows.c
@@ -33,12 +33,15 @@
#include "matahari/logging.h"
#include "matahari/host.h"
+#include "matahari/errors.h"
#include "host_private.h"
static const char CUSTOM_UUID_KEY[] = "CustomUUID";
static const char REBOOT_UUID_KEY[] = "RebootUUID";
+#define BUFSIZE 4096
+
const char *
host_os_get_cpu_flags(void)
{
@@ -394,3 +397,205 @@ host_os_set_custom_uuid(const char *uuid)
return ret;
}
+
+static enum mh_result
+exec_command(const char *apath, char *args[], int atimeout, char **stdoutbuf,
+ char **stderrbuf)
+{
+ enum mh_result res = MH_RES_SUCCESS;
+ DWORD status = 0;
+ gint stdout_fd;
+ gint stderr_fd;
+ HANDLE phandle = NULL;
+ GError *gerr = NULL;
+
+ if (!args || !args[0])
+ return MH_RES_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 MH_RES_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());
+ res = MH_RES_BACKEND_ERROR;
+ }
+
+ if (res == MH_RES_BACKEND_ERROR) {
+ 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);
+
+ if (stdoutbuf) {
+ if (mh_read_from_fd(stdout_fd, stdoutbuf) < 0) {
+ mh_err("Unable to read standard output from command %s.", apath);
+ stdoutbuf = NULL;
+ } else {
+ mh_debug("stdout: %s", *stdoutbuf);
+ }
+ }
+
+ if (stderrbuf) {
+ if (mh_read_from_fd(stderr_fd, stderrbuf) < 0) {
+ mh_err("Unable to read standard error output from command %s.", apath);
+ stderrbuf = NULL;
+ } else {
+ mh_debug("stderr: %s", *stderrbuf);
+ }
+ }
+
+ _close(stdout_fd);
+ _close(stderr_fd);
+
+ g_spawn_close_pid((GPid *) phandle);
+
+ return res;
+}
+
+static gboolean
+get_profiles(GList **names, GList **guids)
+{
+ gboolean rc = FALSE;
+ int len;
+ char *stdoutbuf = 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, NULL)
+ == MH_RES_SUCCESS && stdoutbuf) {
+ rc = TRUE;
+ len = strlen(stdoutbuf);
+ c1 = stdoutbuf;
+
+ // powercfg command returns lines with profiles, that looks like:
+ // "Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)"
+ // So we will take word after "GUID: " as GUID and word in brackets
+ // as name of the profile
+ while ((c1 = strstr(c1, GUID))) {
+ c1 += strlen(GUID);
+ // c1 is now after "GUID: "
+ if (c1 - stdoutbuf < len && (c2 = strchr(c1, ' '))) {
+ // c2 points to end of uuid, put \0 there
+ *c2 = '\0';
+ // Add guid to the list
+ *guids = g_list_append(*guids, strdup(c1));
+ // Put \n back, so the string can be freed
+ *c2 = '\n';
+ // Now find name in brackets
+ if ((c1 = strchr(c2, '(')) && ++c1 - stdoutbuf < len &&
+ (c2 = strchr(c1, ')'))) {
+ // Append profile name to the list
+ *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);
+ return rc;
+}
+
+enum mh_result
+host_os_set_power_profile(const char *profile)
+{
+ enum mh_result res = MH_RES_SUCCESS;
+ char *guid = NULL;
+ GList *names = NULL;
+ GList *guids = NULL;
+ GList *pnames = NULL;
+ GList *pguids = NULL;
+ char *args[4] = {0};
+
+ if (!get_profiles(&names, &guids)) {
+ return MH_RES_BACKEND_ERROR;
+ }
+
+ 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;
+ res = exec_command(getenv("WINDIR"), args, TIMEOUT, NULL, NULL);
+ free(guid);
+ } else {
+ res = MH_RES_INVALID_ARGS;
+ }
+ return res;
+}
+
+enum mh_result
+host_os_get_power_profile(char **profile)
+{
+ enum mh_result res;
+ char *stdoutbuf = NULL;
+ char *c1, *c2;
+ char *args[3] = {0};
+
+ args[0] = SYSTEM32 "\\" POWERCFG;
+ args[1] = PC_GETPROFILE;
+ args[2] = NULL;
+
+ res = exec_command(getenv("WINDIR"), args, TIMEOUT, &stdoutbuf, NULL);
+ if (res == MH_RES_SUCCESS) {
+ // Profile name is string between brackets
+ if (stdoutbuf && (c1 = strchr(stdoutbuf, '(')) &&
+ ++c1 - stdoutbuf < strlen(stdoutbuf) && (c2 = strchr(c1, ')'))) {
+ *c2 = '\0';
+ *profile = strdup(c1);
+ *c2 = ')';
+ } else {
+ res = MH_RES_BACKEND_ERROR;
+ }
+ }
+ free(stdoutbuf);
+
+ return res;
+}
+
+GList *
+host_os_list_power_profiles(void)
+{
+ GList *names = NULL;
+ GList *guids = NULL;
+
+ get_profiles(&names, &guids);
+ g_list_free_full(guids, free);
+
+ return names;
+}
diff --git a/src/lib/utilities.c b/src/lib/utilities.c
index 8da6b44..d62f76e 100644
--- a/src/lib/utilities.c
+++ b/src/lib/utilities.c
@@ -545,3 +545,28 @@ mh_result_to_str(enum mh_result res)
}
return "FIXME: result code doesn't have message assigned!";
}
+
+gsize
+mh_read_from_fd(int fd, char **data)
+{
+ gsize length;
+ GError *err = NULL;
+ GIOChannel *ch;
+
+#ifdef WIN32
+ ch = g_io_channel_win32_new_fd(fd);
+#else
+ ch = g_io_channel_unix_new(fd);
+#endif
+
+ if (g_io_channel_read_to_end(ch, data, &length, &err) != G_IO_STATUS_NORMAL) {
+ mh_err("Unable to read from filedescriptor %d: %s", fd, err->message);
+ free(*data);
+ data = NULL;
+ return -err->code;
+ }
+ g_io_channel_close(ch);
+ g_io_channel_unref(ch);
+ return length;
+}
+
diff --git a/src/unittests/mh_api_host.h b/src/unittests/mh_api_host.h
index 00287ca..56b3feb 100644
--- a/src/unittests/mh_api_host.h
+++ b/src/unittests/mh_api_host.h
@@ -163,6 +163,43 @@ class MhApiHostSuite : public CxxTest::TestSuite
infomsg.str("");
}
+ void testPowerManagement(void)
+ {
+ char *original, *newProfile;
+ const char *profile;
+ GList *profiles;
+ guint len;
+
+ srand(time(NULL));
+
+ // Save the original profile
+ TS_ASSERT(mh_host_get_power_profile(&original) == MH_RES_SUCCESS);
+
+ // List all profiles
+ profiles = mh_host_list_power_profiles();
+ len = g_list_length(profiles);
+
+ // Check if at least one profile is present
+ TS_ASSERT(len > 0);
+
+ // Choose random profile
+ profile = (const char *) g_list_nth(profiles, rand() % len)->data;
+
+ // Set it
+ TS_ASSERT(mh_host_set_power_profile(profile) == MH_RES_SUCCESS);
+
+ // Check if the profile is set
+ TS_ASSERT(mh_host_get_power_profile(&newProfile) == MH_RES_SUCCESS);
+
+ TS_ASSERT(strcmp(newProfile, profile) == 0);
+
+ // Restore original profile
+ TS_ASSERT(mh_host_set_power_profile(original) == MH_RES_SUCCESS);
+
+ free(original);
+ free(newProfile);
+ g_list_free_full(profiles, free);
+ }
};
#endif
--
1.7.7
12 years, 7 months
[PATCH] Core: Export an "Agent" object from all agents
by Zane Bitter
The agent object lists the name and UUID of the host, so a query on these
objects can be used to obtain a list of agents running on each host. This
feature will be exploited by the matahari shell (mhsh).
Signed-off-by: Zane Bitter <zbitter(a)redhat.com>
---
src/lib/mh_agent.cpp | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/src/lib/mh_agent.cpp b/src/lib/mh_agent.cpp
index 49098b0..7c94c7f 100644
--- a/src/lib/mh_agent.cpp
+++ b/src/lib/mh_agent.cpp
@@ -38,6 +38,8 @@
#include <qpid/agent/ManagementAgent.h>
#include <qpid/client/ConnectionSettings.h>
#include <qmf/DataAddr.h>
+#include <qmf/Schema.h>
+#include <qmf/SchemaProperty.h>
#include "matahari/agent.h"
extern "C" {
@@ -67,6 +69,9 @@ struct MatahariAgentImpl {
qmf::AgentSession _agent_session;
qpid::messaging::Connection _amqp_connection;
+
+ qmf::Data _agent_instance;
+ void registerAgent(void);
};
@@ -615,6 +620,34 @@ qmf::AgentSession& MatahariAgent::getSession(void)
return _impl->_agent_session;
}
+void
+MatahariAgentImpl::registerAgent(void)
+{
+ qmf::Schema data_Agent(qmf::SCHEMA_TYPE_DATA,
+ "org.matahariproject", "Agent");
+ {
+ qmf::SchemaProperty prop("hostname", qmf::SCHEMA_DATA_STRING);
+ prop.setAccess(qmf::ACCESS_READ_ONLY);
+ prop.setIndex(true);
+ prop.setDesc("Hostname");
+ data_Agent.addProperty(prop);
+ }
+ {
+ qmf::SchemaProperty prop("uuid", qmf::SCHEMA_DATA_STRING);
+ prop.setAccess(qmf::ACCESS_READ_ONLY);
+ prop.setIndex(true);
+ prop.setDesc("Filesystem Host UUID");
+ data_Agent.addProperty(prop);
+ }
+
+ _agent_session.registerSchema(data_Agent);
+
+ _agent_instance = qmf::Data(data_Agent);
+ _agent_instance.setProperty("uuid", mh_uuid());
+ _agent_instance.setProperty("hostname", mh_hostname());
+ _agent_session.addData(_agent_instance);
+}
+
static bool
mh_hastty(void)
{
@@ -664,6 +697,8 @@ MatahariAgent::init(int argc, char **argv, const char* proc_name)
goto return_cleanup;
}
+ _impl->registerAgent();
+
_impl->_mainloop = g_main_new(FALSE);
_impl->_qpid_source = mainloop_add_qmf(G_PRIORITY_HIGH, _impl->_agent_session,
mh_qpid_callback, mh_qpid_disconnect,
12 years, 7 months
initial ubuntu packaging for sigar
by Adam Stokes
http://astokes.fedorapeople.org/sigar-debian/
Anyone with ubuntu 64bit that could test this I would appreciate it.
As far as keeping debian packaging files in the git repository I think
it'll be a good idea to have distro specific folders under contrib. For
debian/ubuntu the only files we'd need to keep are whats found in
package-src/debian directory.
Thanks
adam
12 years, 7 months
Matahari Shell requirements
by Zane Bitter
This is a first attempt at coming up with some requirements for the
proposed Matahari shell. It's mostly in the form of random things I've
been thinking about, so at this stage everything is up for grabs. If
anybody else has ideas floating around in their heads about what the
shell should be, now would be a good time to get them out.
cheers,
Zane.
The shell needs to support the following:
- Query for objects; filter by any combination of:
+ Broker (?) [How does this work with federated brokers?]
+ Package
+ Class
+ Property value
- Read properties/statistics of objects
- Wait for events (?)
- Invoke methods
- Perform introspection: list and get types of properties, statistics,
methods, method parameters
Configuration:
- The shell should read the /etc/sysconfig/matahari file for
configuration of the broker, port, SSL &c.
- There should be CLI options to override those values. Where possible
these should match those used by the Matahari agents/consoles.
Consumers:
The shell should be accessible both interactively to CLI users and to
external scripts (e.g. bash scripts) that want to make use of it.
Features such as tab completion are a low priority initially, but we
will want them in the long term. Readline support (e.g. command history)
and online help will probably be required from the outset.
There are broadly two approaches to shell design that could be followed:
- 1) Stateless:
All of the data needed to execute a particular command must be entered
as parameters.
+ Downside: it's a pain for an interactive user, especially when
performing multiple actions on a single object.
- 2) Stateful:
Switch between various modes that retain data about the current state so
that it does not need to be entered as parameters every time. e.g. the
Cisco IOS command line.
+ Downside: it can mean that scripts using the shell also have to
maintain state.
qmf-tool uses a hybrid of these two approches that arguably incorporates
the downsides of both ;)
On balance I would recommend some kind of stateful model, but with an
emphasis on making it easy for scripts to inspect the current state, or
at least return to a known state.
Parallelisation:
The QMF Python libraries support asynchronous method calls. Therefore we
can, in theory, implement the shell in such a way that methods can be
invoked on an entire group of objects (selected by some query) at once.
This seems to be one of the big selling points of things like
MCollective, which goes out of its way to say that "we’re not simply a
fancy SSH “for loop.” MCollective use modern tools like Publish
Subscribe Middleware and modern philosophies like real time discovery of
network resources using meta data and not hostnames. Delivering a very
scalable and very fast parallel execution environment." Matahari is
built on top of QMF for the same reasons; do we need to exploit that in
the shell?
Other Considerations:
- We already have qmf-tool. What do we need to do better/differently
in a Matahari shell?
- Ideally the CLI part should be a wrapper over a Python API, so that
authors of Python scripts can consume the API directly.
12 years, 7 months
feature tracking
by Perry Myers
We've been tracking todo/in progress/completed features here:
https://github.com/matahari/matahari/wiki/Backlog
But as time goes on this list is getting a little unwieldy. Editing the
tables in this wiki format is not easy, and there's no data querying on
a wiki page :)
We had already created a home for Matahari in bugzilla here:
https://bugzilla.redhat.com/buglist.cgi?product=Matahari
This is on Red Hat bugzilla, but it's in the "Community" section which
means it is intended to be distro neutral. It's meant for the 'upstream
codebase' not for any particular distro/platform.
Distro specific bugs would go into their respective distros (for example
the Fedora product in Bugzilla)
The thought is that we could use bugzilla for tracking upstream features
in a slightly more coherent and trackable way than a wiki page.
Are there better bug tracking/feature tracking systems out there?
Probably yes. But I'm thinking: low overhead, high return. And
utilizing an existing hosted system seems to be a win here.
So to give folks an idea of how we might translate this wiki page into
bugzillas, here's an example:
https://bugzilla.redhat.com/show_bug.cgi?id=747978
Took 1 minute to file. Basically:
* set $subject (preface with [RFE] perhaps to distinguish from bugs)
* add some detail to Description
We might also want to:
* Set the Target Release (we'll need to populate this with things like
0.5.0, 0.6.0, etc)
* Set the Priority field accordingly (High, Med, Low)
* Assign to relevant person (or leave default)
When someone is working on a feature, they can assign it to themselves
and move to ASSIGNED
The only other state I think we really need to use upstream is CLOSED.
Feature finished, CLOSED->CURRENTRELEASE. Feature nacked,
CLOSED->WONTFIX/CANTFIX, etc, etc
Thoughts? If folks think this is a good idea, I am happy to do the evil
work of translating the wiki into bugs.
Perry
12 years, 7 months
[PATCH] schema.xml cleanup
by Radek Novacek
* Fix indentation - constistenly use 4 space for indentation
* Add some documentation for resources API (already acked)
* Adapt for change of Matahari manual generation script (using xref for linking between methods, etc.)
Some changes require patched manual generation script, see the next patch.
---
src/host/schema.xml | 152 +++++++++---------
src/network/schema.xml | 56 +++---
src/service/schema.xml | 411 +++++++++++++++++++++++++---------------------
src/sysconfig/schema.xml | 76 +++++----
4 files changed, 373 insertions(+), 322 deletions(-)
diff --git a/src/host/schema.xml b/src/host/schema.xml
index cb179cf..1841907 100644
--- a/src/host/schema.xml
+++ b/src/host/schema.xml
@@ -1,99 +1,97 @@
<schema package="org.matahariproject">
- <eventArguments>
+ <eventArguments>
+ <arg name="timestamp" type="absTime" />
+ <arg name="sequence" type="uint32" />
+ <arg name="hostname" type="sstr"/>
+ <arg name="uuid" type="sstr"/>
+ </eventArguments>
- <arg name="timestamp" type="absTime" />
- <arg name="sequence" type="uint32" />
- <arg name="hostname" type="sstr"/>
- <arg name="uuid" type="sstr"/>
+ <class name="Host">
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
+ <property name="uuid" type="sstr" access="RO" desc="Filesystem Host UUID" index="y" />
+ <property name="custom_uuid" type="sstr" access="RO" desc="Custom Host UUID" index="y" />
- </eventArguments>
+ <property name="os" type="sstr" access="RO" desc="The installed operating system." />
+ <property name="arch" type="sstr" access="RO" desc="The host's architecture" />
+ <property name="wordsize" type="uint8" access="RO" desc="The wordsize for the host" unit="bit"/>
- <class name="Host">
- <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
- <property name="uuid" type="sstr" access="RO" desc="Filesystem Host UUID" index="y" />
- <property name="custom_uuid" type="sstr" access="RO" desc="Custom Host UUID" index="y" />
+ <property name="memory" type="uint64" access="RO" desc="Amount of primary memory for host" unit="kb" />
+ <property name="swap" type="uint64" access="RO" desc="Amount of swap for host" unit="kb" />
- <property name="os" type="sstr" access="RO" desc="The installed operating system." />
- <property name="arch" type="sstr" access="RO" desc="The host's architecture" />
- <property name="wordsize" type="uint8" access="RO" desc="The wordsize for the host" unit="bit"/>
+ <property name="cpu_count" type="uint8" access="RO" desc="The number of logical CPUs." />
+ <property name="cpu_cores" type="uint8" access="RO" desc="The total number of processor cores." />
+ <property name="cpu_model" type="lstr" access="RO" desc="The processor(s) model description." />
+ <property name="cpu_flags" type="lstr" access="RO" desc="The processor(s) CPU flags." />
- <property name="memory" type="uint64" access="RO" desc="Amount of primary memory for host" unit="kb" />
- <property name="swap" type="uint64" access="RO" desc="Amount of swap for host" unit="kb" />
+ <property name="update_interval" type="uint32" access="RW" desc="The interval at which the host sends out heartbeats and refreshes statistics." unit="s"/>
- <property name="cpu_count" type="uint8" access="RO" desc="The number of logical CPUs." />
- <property name="cpu_cores" type="uint8" access="RO" desc="The total number of processor cores." />
- <property name="cpu_model" type="lstr" access="RO" desc="The processor(s) model description." />
- <property name="cpu_flags" type="lstr" access="RO" desc="The processor(s) CPU flags." />
+ <statistic name="last_updated" type="absTime" desc="The last time a heartbeat occurred." />
+ <statistic name="sequence" type="uint32" desc="The heartbeat sequence number." />
- <property name="update_interval" type="uint32" access="RW" desc="The interval at which the host sends out heartbeats and refreshes statistics." unit="s"/>
+ <statistic name="free_mem" type="uint64" desc="Amount of available memory for host" unit="kb" />
+ <statistic name="free_swap" type="uint64" desc="Amount of available swap for host" unit="kb" />
- <statistic name="last_updated" type="absTime" desc="The last time a heartbeat occurred." />
- <statistic name="sequence" type="uint32" desc="The heartbeat sequence number." />
+ <statistic name="load" type="map" desc="The one/five/fifteen minute load average" />
+ <statistic name="process_statistics" type="map" desc="Number of processes in each possible state" />
- <statistic name="free_mem" type="uint64" desc="Amount of available memory for host" unit="kb" />
- <statistic name="free_swap" type="uint64" desc="Amount of available swap for host" unit="kb" />
+ <method name="identify" desc="Tell the host to beep its pc speaker." />
+ <method name="shutdown" desc="Shutdown node" />
+ <method name="reboot" desc="Reboot node" />
- <statistic name="load" type="map" desc="The one/five/fifteen minute load average" />
- <statistic name="process_statistics" type="map" desc="Number of processes in each possible state" />
+ <!--
+ <variablelist><title>Valid UUID lifetimes:</title>
- <method name="identify" desc="Tell the host to beep its pc speaker." />
- <method name="shutdown" desc="Shutdown node" />
- <method name="reboot" desc="Reboot node" />
+ <varlistentry><term><literal>Filesystem</literal></term>
+ <listitem><para>
+ Automatically configured by the system during
+ installation and never reset. May be pre-populated.
+ </para></listitem>
+ </varlistentry>
- <!--
- <variablelist><title>Valid UUID lifetimes:</title>
+ <varlistentry><term><literal>Hardware</literal></term>
+ <listitem><para>
+ UUID supplied by or generated from the underlying hardware.
+ </para></listitem>
+ </varlistentry>
- <varlistentry><term><literal>Filesystem</literal></term>
- <listitem><para>
- Automatically configured by the system during
- installation and never reset. May be pre-populated.
- </para></listitem>
- </varlistentry>
+ <varlistentry><term><literal>Reboot</literal></term>
+ <listitem><para>
+ Automatically (re)configured by the system whenever it boots.
+ </para></listitem>
+ </varlistentry>
- <varlistentry><term><literal>Hardware</literal></term>
- <listitem><para>
- UUID supplied by or generated from the underlying hardware.
- </para></listitem>
- </varlistentry>
+ <varlistentry><term><literal>Agent</literal></term>
+ <listitem><para>
+ Automatically (re)configured by the agent whenever it starts
+ </para></listitem>
+ </varlistentry>
- <varlistentry><term><literal>Reboot</literal></term>
- <listitem><para>
- Automatically (re)configured by the system whenever it boots.
- </para></listitem>
- </varlistentry>
+ <varlistentry><term><literal>Custom</literal></term>
+ <listitem><para>
+ Manually configured by the admin/user using the set_uuid method.
+ </para></listitem>
+ </varlistentry>
- <varlistentry><term><literal>Agent</literal></term>
- <listitem><para>
- Automatically (re)configured by the agent whenever it starts
- </para></listitem>
- </varlistentry>
+ </variablelist>
+ -->
+ <method name="get_uuid" desc="Obtain a UUID with the specified lifetime from the machine" >
+ <arg name="lifetime" dir="I" type="sstr" />
+ <arg name="uuid" dir="O" type="sstr" />
+ </method>
- <varlistentry><term><literal>Custom</literal></term>
- <listitem><para>
- Manually configured by the admin/user using the set_uuid method.
- </para></listitem>
- </varlistentry>
+ <!--
+ <para>The only valid lifetime for <literal>set_uuid</literal> is <literal>Custom</literal>.
+ Later implementations may support re-generating the 'Hardware' uuid.
+ </para>
+ -->
+ <method name="set_uuid" desc="Set a UUID with the specified lifetime" >
+ <arg name="lifetime" dir="I" type="sstr" />
+ <arg name="uuid" dir="I" type="sstr" />
+ <arg name="rc" dir="O" type="int32" />
+ </method>
+ </class>
- </variablelist>
- -->
- <method name="get_uuid" desc="Obtain a UUID with the specified lifetime from the machine" >
- <arg name="lifetime" dir="I" type="sstr" />
- <arg name="uuid" dir="O" type="sstr" />
- </method>
-
- <!--
- <para>The only valid lifetime for <literal>set_uuid</literal> is <literal>Custom</literal>.
- Later implementations may support re-generating the 'Hardware' uuid.</para>
- -->
- <method name="set_uuid" desc="Set a UUID with the specified lifetime" >
- <arg name="lifetime" dir="I" type="sstr" />
- <arg name="uuid" dir="I" type="sstr" />
- <arg name="rc" dir="O" type="int32" />
- </method>
-
- </class>
-
- <event name="heartbeat" args="timestamp,sequence,hostname,uuid" />
+ <event name="heartbeat" args="timestamp,sequence,hostname,uuid" />
</schema>
diff --git a/src/network/schema.xml b/src/network/schema.xml
index 2458bfa..ceb1ef3 100644
--- a/src/network/schema.xml
+++ b/src/network/schema.xml
@@ -1,34 +1,34 @@
<schema package="org.matahariproject">
- <class name="Network">
- <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
- <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
+ <class name="Network">
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y" />
- <statistic name="qmf-gen-no-crash" type="absTime" desc="Dummy stat to stop qmf-gen from crashing." />
+ <statistic name="qmf-gen-no-crash" type="absTime" desc="Dummy stat to stop qmf-gen from crashing." />
- <method name="list" desc="List network interfaces">
- <arg name="iface_map" dir="O" type="list" />
- </method>
- <method name="start" desc="Start a network interface">
- <arg name="iface" dir="I" type="sstr" />
- <arg name="status" dir="O" type="uint32" />
- </method>
- <method name="stop" desc="Stop a network interface">
- <arg name="iface" dir="I" type="sstr" />
- <arg name="status" dir="O" type="uint32" />
- </method>
- <method name="status" desc="Check a network interface">
- <arg name="iface" dir="I" type="sstr" />
- <arg name="status" dir="O" type="uint32" />
- </method>
- <method name="get_ip_address" desc="Obtain ip addressof a network interface">
- <arg name="iface" dir="I" type="sstr" />
- <arg name="ip" dir="O" type="sstr" />
- </method>
- <method name="get_mac_address" desc="Obtain mac address of network interface">
- <arg name="iface" dir="I" type="sstr" />
- <arg name="mac" dir="O" type="sstr" />
- </method>
- </class>
+ <method name="list" desc="List network interfaces">
+ <arg name="iface_map" dir="O" type="list" />
+ </method>
+ <method name="start" desc="Start a network interface">
+ <arg name="iface" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+ <method name="stop" desc="Stop a network interface">
+ <arg name="iface" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+ <method name="status" desc="Check a network interface">
+ <arg name="iface" dir="I" type="sstr" />
+ <arg name="status" dir="O" type="uint32" />
+ </method>
+ <method name="get_ip_address" desc="Obtain ip addressof a network interface">
+ <arg name="iface" dir="I" type="sstr" />
+ <arg name="ip" dir="O" type="sstr" />
+ </method>
+ <method name="get_mac_address" desc="Obtain mac address of network interface">
+ <arg name="iface" dir="I" type="sstr" />
+ <arg name="mac" dir="O" type="sstr" />
+ </method>
+ </class>
</schema>
diff --git a/src/service/schema.xml b/src/service/schema.xml
index 0790eb8..7c6cdb2 100644
--- a/src/service/schema.xml
+++ b/src/service/schema.xml
@@ -1,206 +1,245 @@
<schema package="org.matahariproject">
- <eventArguments>
+ <eventArguments>
+ <arg name="timestamp" type="absTime" />
+ <arg name="sequence" type="uint32" />
- <arg name="timestamp" type="absTime" />
- <arg name="sequence" type="uint32" />
+ <arg name="name" type="sstr" />
+ <arg name="standard" type="sstr" />
+ <arg name="provider" type="sstr" />
+ <arg name="agent" type="sstr" />
- <arg name="name" type="sstr" />
- <arg name="standard" type="sstr" />
- <arg name="provider" type="sstr" />
- <arg name="agent" type="sstr" />
+ <arg name="action" type="sstr" />
+ <arg name="interval" type="uint32" />
+ <arg name="rc" type="uint32" />
- <arg name="action" type="sstr" />
- <arg name="interval" type="uint32" />
- <arg name="rc" type="uint32" />
+ <arg name="expected-rc" type="uint32" />
+ <arg name="userdata" type="sstr" />
+ </eventArguments>
- <arg name="expected-rc" type="uint32" />
- <arg name="userdata" type="sstr" />
+ <event name="resource_op" args="timestamp,sequence,name,standard,provider,agent,action,interval,rc,expected-rc,userdata" />
- </eventArguments>
+ <!--
+ <para>
+ Simple API for accessing system services
+ </para>
- <event name="resource_op" args="timestamp,sequence,name,standard,provider,agent,action,interval,rc,expected-rc,userdata" />
+ <para>
+ For more advanced functionality, use the Resources API with standard="lsb"
+ </para>
+ -->
- <!--
- Services API
- Simple API for accessing system services
-
- For more advanced functionality, use the Resources API with standard="lsb"
- -->
+ <class name="Services">
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y"/>
- <class name="Services">
- <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
- <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y"/>
+ <statistic name="qmf-gen-no-crash" type="absTime" desc="Dummy stat to stop qmf-gen from crashing." />
- <statistic name="qmf-gen-no-crash" type="absTime" desc="Dummy stat to stop qmf-gen from crashing." />
+ <method name="list" desc="List known system services">
+ <arg name="agents" dir="O" type="list" />
+ </method>
+ <method name="enable" desc="Configure a system service to start at boot">
+ <arg name="name" dir="I" type="sstr" />
+ <arg name="rc" dir="O" type="uint32" />
+ </method>
+ <method name="disable" desc="Configure a system service _not_ to start at boot">
+ <arg name="name" dir="I" type="sstr" />
+ <arg name="rc" dir="O" type="uint32" />
+ </method>
+ <method name="start" desc="Start a system service">
+ <arg name="name" dir="I" type="sstr" />
+ <arg name="timeout" dir="I" type="uint32" />
+ <arg name="rc" dir="O" type="uint32" />
+ </method>
+ <method name="stop" desc="Stop a system service">
+ <arg name="name" dir="I" type="sstr" />
+ <arg name="timeout" dir="I" type="uint32" />
+ <arg name="rc" dir="O" type="uint32" />
+ </method>
+ <method name="status" desc="Check the health of a system service">
+ <arg name="name" dir="I" type="sstr" />
+ <arg name="timeout" dir="I" type="uint32" />
+ <arg name="rc" dir="O" type="uint32" />
+ </method>
+ <method name="describe" desc="Obtain XML description of a system service">
+ <arg name="name" dir="I" type="sstr" />
+ <arg name="xml" dir="O" type="sstr" />
+ </method>
+ </class>
- <method name="list" desc="List known system services">
- <arg name="agents" dir="O" type="list" />
- </method>
- <method name="enable" desc="Configure a system service to start at boot">
- <arg name="name" dir="I" type="sstr" />
- <arg name="rc" dir="O" type="uint32" />
- </method>
- <method name="disable" desc="Configure a system service _not_ to start at boot">
- <arg name="name" dir="I" type="sstr" />
- <arg name="rc" dir="O" type="uint32" />
- </method>
- <method name="start" desc="Start a system service">
- <arg name="name" dir="I" type="sstr" />
- <arg name="timeout" dir="I" type="uint32" />
- <arg name="rc" dir="O" type="uint32" />
- </method>
- <method name="stop" desc="Stop a system service">
- <arg name="name" dir="I" type="sstr" />
- <arg name="timeout" dir="I" type="uint32" />
- <arg name="rc" dir="O" type="uint32" />
- </method>
- <method name="status" desc="Check the health of a system service">
- <arg name="name" dir="I" type="sstr" />
- <arg name="timeout" dir="I" type="uint32" />
- <arg name="rc" dir="O" type="uint32" />
- </method>
- <method name="describe" desc="Obtain XML description of a system service">
- <arg name="name" dir="I" type="sstr" />
- <arg name="xml" dir="O" type="sstr" />
- </method>
- </class>
+ <!--
+ <para>
+ Fully featured API for controlling and monitoring services
+ conforming to a standardized specification.
+ </para>
+ <para>
+ Currently supported standards:
+ <literal>windows</literal>,
+ <literal>lsb</literal> (Linux Standard Base),
+ <literal>ocf</literal> (Open Cluster Framework),
+ <literal>systemd</literal>.
+ </para>
+ <para>
+ On Windows, <literal>lsb</literal> is an alias for <literal>windows</literal>.
+ </para>
+ -->
- <!--
- Resources API
+ <class name="Resources">
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y"/>
- Fully featured API for controlling and monitoring services
- conforming to a standardized specification.
-
- Currently supported standards: windows, lsb (Linux Standard Base), ocf (Open Cluster Framework)
- On Windows, 'lsb' is an alias for 'windows'
- -->
+ <method name="list_standards" desc="List known resource standards (OCF, LSB, systemd, etc)">
+ <arg name="standards" dir="O" type="list" />
+ </method>
- <class name="Resources">
- <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
- <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y"/>
+ <method name="list_providers" desc="List known providers (if supported) for a given standard">
+ <arg name="standard" dir="I" type="sstr" />
+ <arg name="providers" dir="O" type="list" />
+ </method>
- <method name="list_standards" desc="List known resource standards (OCF, LSB, Upstart, etc)">
- <arg name="standards" dir="O" type="list" />
- </method>
- <method name="list_providers" desc="List known providers (if supported) for a given standard">
- <arg name="standard" dir="I" type="sstr" />
- <arg name="providers" dir="O" type="list" />
- </method>
- <method name="list" desc="List known resource types for a given standard and provider">
- <arg name="standard" dir="I" type="sstr" />
- <arg name="provider" dir="I" type="sstr" />
- <arg name="agents" dir="O" type="list" />
- </method>
+ <method name="list" desc="List known resource types for a given standard and provider">
+ <arg name="standard" dir="I" type="sstr" />
+ <arg name="provider" dir="I" type="sstr" />
+ <arg name="agents" dir="O" type="list" />
+ </method>
- <method name="describe" desc="Obtain XML description of a resource">
- <arg name="standard" dir="I" type="sstr" />
- <arg name="provider" dir="I" type="sstr" />
- <arg name="agent" dir="I" type="sstr" />
- <arg name="xml" dir="O" type="sstr" />
- </method>
- <!--
- <para>The <literal>rc</literal> output parameter warrants some additional discussion.
- The potential return values depends on which <literal>standard</literal> is being
- used. In the case of <literal>OCF</literal>, these values are defined by the
- <ulink url="http://www.opencf.org/cgi-bin/viewcvs.cgi/specs/ra/resource-agent-api.txt...">OCF
- resource agent specification</ulink>. However, see <xref linkend="ocf_return_vals"/>
- for an overview of the OCF resource agent return codes.</para>
+ <method name="describe" desc="Obtain XML description of a resource">
+ <arg name="standard" dir="I" type="sstr" />
+ <arg name="provider" dir="I" type="sstr" />
+ <arg name="agent" dir="I" type="sstr" />
+ <arg name="xml" dir="O" type="sstr" />
+ </method>
- <table id="ocf_return_vals">
- <title>OCF Resource Agent Exit Codes</title>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Value(s)</entry>
- <entry>OCF Name</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><literal>0</literal></entry>
- <entry><literal>OCF_SUCCESS</literal></entry>
- <entry>Success. The command complete successfully. This is the expected result for all start, stop, promote and demote commands.</entry>
- </row>
- <row>
- <entry><literal>1</literal></entry>
- <entry><literal>OCF_ERR_GENERIC</literal></entry>
- <entry>Generic "there was a problem" error code.</entry>
- </row>
- <row>
- <entry><literal>2</literal></entry>
- <entry><literal>OCF_ERR_ARGS</literal></entry>
- <entry>The resource's configuration is not valid on this machine. Eg. Refers to a location/tool not found on the node.</entry>
- </row>
- <row>
- <entry><literal>3</literal></entry>
- <entry><literal>OCF_ERR_UNIMPLEMENTED</literal></entry>
- <entry>The requested action is not implemented.</entry>
- </row>
- <row>
- <entry><literal>4</literal></entry>
- <entry><literal>OCF_ERR_PERM</literal></entry>
- <entry>The resource agent does not have sufficient privileges to complete the task.</entry>
- </row>
- <row>
- <entry><literal>5</literal></entry>
- <entry><literal>OCF_ERR_INSTALLED</literal></entry>
- <entry>The tools required by the resource are not installed on this machine.</entry>
- </row>
- <row>
- <entry><literal>6</literal></entry>
- <entry><literal>OCF_ERR_CONFIGURED</literal></entry>
- <entry>The resource's configuration is invalid. Eg. A required parameters are missing.</entry>
- </row>
- <row>
- <entry><literal>7</literal></entry>
- <entry><literal>OCF_NOT_RUNNING</literal></entry>
- <entry>The resource is safely stopped.</entry>
- </row>
- <row>
- <entry><literal>8</literal></entry>
- <entry><literal>OCF_RUNNING_MASTER</literal></entry>
- <entry>The resource is running in Master mode.</entry>
- </row>
- <row>
- <entry><literal>9</literal></entry>
- <entry><literal>OCF_FAILED_MASTER</literal></entry>
- <entry>The resource is in Master mode but has failed. The resource will be demoted, stopped and then started (and possibly promoted) again.</entry>
- </row>
- <row>
- <entry>other</entry>
- <entry>N/A</entry>
- <entry>Custom error code.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- -->
- <method name="invoke" desc="Perform a custom action on a resource">
- <arg name="name" dir="I" type="sstr" />
- <arg name="standard" dir="I" type="sstr" />
- <arg name="provider" dir="I" type="sstr" />
- <arg name="agent" dir="I" type="sstr" />
- <arg name="action" dir="I" type="sstr" />
- <arg name="interval" dir="I" type="uint32" />
- <arg name="parameters" dir="I" type="map" />
- <arg name="timeout" dir="I" type="uint32" />
- <arg name="expected-rc" dir="I" type="uint32" />
- <arg name="rc" dir="O" type="uint32" />
- <arg name="sequence" dir="O" type="uint32" />
- <arg name="userdata" dir="IO" type="sstr" />
- </method>
- <method name="cancel" desc="Cancel a pending or running action on a resource">
- <arg name="name" dir="I" type="sstr" />
- <arg name="action" dir="I" type="sstr" />
- <arg name="interval" dir="I" type="uint32" />
- <arg name="timeout" dir="I" type="uint32" />
- </method>
- <method name="fail" desc="Indicate a resource has failed">
- <arg name="name" dir="I" type="sstr" />
- <arg name="rc" dir="I" type="uint32" />
- </method>
- </class>
+ <!--
+ <para>
+ <literal>action</literal> depends on the standard/provider/agent
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>OCF</literal>: see
+ <ulink url="http://www.opencf.org/cgi-bin/viewcvs.cgi/specs/ra/resource-agent-api.txt...">
+ ocf specification
+ </ulink>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LSB</literal>: enable/disable/start/stop/status
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>systemd</literal>: see
+ <ulink url="http://www.linuxcertif.com/man/1/systemctl/">
+ man systemctl
+ </ulink>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The <literal>rc</literal> output parameter warrants some additional discussion.
+ The potential return values depends on which <literal>standard</literal> is being
+ used. In the case of <literal>OCF</literal>, these values are defined by the
+ <ulink url="http://www.opencf.org/cgi-bin/viewcvs.cgi/specs/ra/resource-agent-api.txt...">OCF
+ resource agent specification</ulink>. However, see <xref linkend="ocf_return_vals"/>
+ for an overview of the OCF resource agent return codes.
+ </para>
+
+ <table id="ocf_return_vals">
+ <title>OCF Resource Agent Exit Codes</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Value(s)</entry>
+ <entry>OCF Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>0</literal></entry>
+ <entry><literal>OCF_SUCCESS</literal></entry>
+ <entry>Success. The command complete successfully. This is the expected result for all start, stop, promote and demote commands.</entry>
+ </row>
+ <row>
+ <entry><literal>1</literal></entry>
+ <entry><literal>OCF_ERR_GENERIC</literal></entry>
+ <entry>Generic "there was a problem" error code.</entry>
+ </row>
+ <row>
+ <entry><literal>2</literal></entry>
+ <entry><literal>OCF_ERR_ARGS</literal></entry>
+ <entry>The resource's configuration is not valid on this machine. Eg. Refers to a location/tool not found on the node.</entry>
+ </row>
+ <row>
+ <entry><literal>3</literal></entry>
+ <entry><literal>OCF_ERR_UNIMPLEMENTED</literal></entry>
+ <entry>The requested action is not implemented.</entry>
+ </row>
+ <row>
+ <entry><literal>4</literal></entry>
+ <entry><literal>OCF_ERR_PERM</literal></entry>
+ <entry>The resource agent does not have sufficient privileges to complete the task.</entry>
+ </row>
+ <row>
+ <entry><literal>5</literal></entry>
+ <entry><literal>OCF_ERR_INSTALLED</literal></entry>
+ <entry>The tools required by the resource are not installed on this machine.</entry>
+ </row>
+ <row>
+ <entry><literal>6</literal></entry>
+ <entry><literal>OCF_ERR_CONFIGURED</literal></entry>
+ <entry>The resource's configuration is invalid. Eg. A required parameters are missing.</entry>
+ </row>
+ <row>
+ <entry><literal>7</literal></entry>
+ <entry><literal>OCF_NOT_RUNNING</literal></entry>
+ <entry>The resource is safely stopped.</entry>
+ </row>
+ <row>
+ <entry><literal>8</literal></entry>
+ <entry><literal>OCF_RUNNING_MASTER</literal></entry>
+ <entry>The resource is running in Master mode.</entry>
+ </row>
+ <row>
+ <entry><literal>9</literal></entry>
+ <entry><literal>OCF_FAILED_MASTER</literal></entry>
+ <entry>The resource is in Master mode but has failed. The resource will be demoted, stopped and then started (and possibly promoted) again.</entry>
+ </row>
+ <row>
+ <entry>other</entry>
+ <entry>N/A</entry>
+ <entry>Custom error code.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ -->
+ <method name="invoke" desc="Perform a custom action on a resource">
+ <arg name="name" dir="I" type="sstr" desc="Identification of the action" />
+ <arg name="standard" dir="I" type="sstr" desc="Resource standard to be used, see <xref linkend='Resources_list_standards' />" />
+ <arg name="provider" dir="I" type="sstr" desc="Provider of ocf standard, see <xref linkend='Resources_list_providers' />" />
+ <arg name="agent" dir="I" type="sstr" desc="Name of the resource affected by action" />
+ <arg name="action" dir="I" type="sstr" desc="Action that will be executed on resource" />
+ <arg name="interval" dir="I" type="uint32" desc="Event resource_op will be risen each interval miliseconds (not supported by dbus agent)" />
+ <arg name="parameters" dir="I" type="map" desc="Additional parameters for the action (enviromental variables for OCF)" />
+ <arg name="timeout" dir="I" type="uint32" desc="Timeout for the action in miliseconds" />
+ <arg name="expected-rc" dir="I" type="uint32" />
+ <arg name="rc" dir="O" type="uint32" desc="Return code of the action" />
+ <arg name="sequence" dir="O" type="uint32" />
+ <arg name="userdata" dir="IO" type="sstr" />
+ </method>
+ <method name="cancel" desc="Cancel a pending or running action on a resource. name, action and interval must be the same as for invoke method">
+ <arg name="name" dir="I" type="sstr" desc="Identification of the action" />
+ <arg name="action" dir="I" type="sstr" desc="Action that is running or pending" />
+ <arg name="interval" dir="I" type="uint32" desc="Interval in miliseconds" />
+ <arg name="timeout" dir="I" type="uint32" desc="Timeout for cancelling in miliseconds" />
+ </method>
+ <method name="fail" desc="Indicate a resource has failed">
+ <arg name="name" dir="I" type="sstr" />
+ <arg name="rc" dir="I" type="uint32" />
+ </method>
+ </class>
</schema>
diff --git a/src/sysconfig/schema.xml b/src/sysconfig/schema.xml
index bc41a55..0635a09 100644
--- a/src/sysconfig/schema.xml
+++ b/src/sysconfig/schema.xml
@@ -1,48 +1,62 @@
<schema package="org.matahariproject">
- <!-- Config API -->
+ <!--
+ <para>
+ API for system configuration.
+ </para>
+ -->
<class name="Sysconfig">
- <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
- <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y"/>
+ <property name="uuid" type="sstr" access="RO" desc="Host UUID" />
+ <property name="hostname" type="sstr" access="RO" desc="Hostname" index="y"/>
<!--
- <para>It is useful to have some information in a property since you can
- filter on properties. This property is intended to be used as a
- flag to know whether or not initial configuration of a host has
- been done or not. It is not automatically set. Once the
- configuring entity has completed its tasks, it should set this
- property itself.</para>
+ <para>
+ It is useful to have some information in a property since you can
+ filter on properties. This property is intended to be used as a
+ flag to know whether or not initial configuration of a host has
+ been done or not. It is not automatically set. Once the
+ configuring entity has completed its tasks, it should set this
+ property itself.
+ </para>
-->
- <property name="is_postboot_configured" type="uint32" access="RW" desc="Set if agent is configured." />
+ <property name="is_postboot_configured" type="uint32" access="RW" desc="Set if agent is configured." />
- <statistic name="qmf-gen-no-crash" type="absTime" desc="Dummy stat to stop qmf-gen from crashing." />
+ <statistic name="qmf-gen-no-crash" type="absTime" desc="Dummy stat to stop qmf-gen from crashing." />
- <method name="run_uri" desc="Send configure uri method">
- <arg name="uri" dir="I" type="sstr" />
- <arg name="flags" dir="I" type="uint32" />
- <arg name="scheme" dir="I" type="sstr" />
- <arg name="key" dir="I" type="sstr" />
- <arg name="status" dir="O" type="sstr" />
+ <method name="run_uri" desc="Configure system using configuration file on given uri">
+ <arg name="uri" dir="I" type="sstr" desc="URI with configuration file. Same protocols as cURL are supported." />
+ <arg name="flags" dir="I" type="uint32" desc="
+ <itemizedlist>
+ <listitem>
+ <para><literal>0</literal>: no flag,</para>
+ </listitem>
+ <listitem>
+ <para><literal>1</literal>: force execution. Use this if the <literal>key</literal> is already set.</para>
+ </listitem>
+ </itemizedlist>" />
+ <arg name="scheme" dir="I" type="sstr" desc="File format of configuration file. Currently supported are <literal>puppet</literal> and <literal>augeas</literal>." />
+ <arg name="key" dir="I" type="sstr" desc="Key will be associated with the result of the command. The key can be used in <xref linkend='Sysconfig_is_configured' />." />
+ <arg name="status" dir="O" type="sstr" desc="Result of the command." />
</method>
- <method name="run_string" desc="Send configure text method">
- <arg name="text" dir="I" type="sstr" />
- <arg name="flags" dir="I" type="uint32" />
- <arg name="scheme" dir="I" type="sstr" />
- <arg name="key" dir="I" type="sstr" />
- <arg name="status" dir="O" type="sstr" />
+ <method name="run_string" desc="Configure system using given configuration text. Most arguments are the same as <xref linkend='Sysconfig_run_uri' />">
+ <arg name="text" dir="I" type="sstr" desc="Configuration string" />
+ <arg name="flags" dir="I" type="uint32" desc="" />
+ <arg name="scheme" dir="I" type="sstr" desc="" />
+ <arg name="key" dir="I" type="sstr" desc="" />
+ <arg name="status" dir="O" type="sstr" desc="" />
</method>
- <method name="query" desc="Perform query lookup">
- <arg name="text" dir="I" type="sstr" />
- <arg name="flags" dir="I" type="uint32" />
- <arg name="scheme" dir="I" type="sstr" />
- <arg name="data" dir="O" type="sstr" />
+ <method name="query" desc="Perform query lookup">
+ <arg name="text" dir="I" type="sstr" desc="Text of the query." />
+ <arg name="flags" dir="I" type="uint32" desc="Not used now." />
+ <arg name="scheme" dir="I" type="sstr" desc="Only <literal>augeas</literal> is supported." />
+ <arg name="data" dir="O" type="sstr" desc="Result of the query." />
</method>
- <method name="is_configured" desc="Check if system is configured">
- <arg name="key" dir="I" type="sstr" />
- <arg name="status" dir="O" type="sstr" />
+ <method name="is_configured" desc="Check if system is configured">
+ <arg name="key" dir="I" type="sstr" desc="Configuration key" />
+ <arg name="status" dir="O" type="sstr" desc="Result of command associated with the key" />
</method>
</class>
</schema>
--
1.7.7
12 years, 7 months
[PATCH] windows: verify uninstallation actually uninstalls what it is supposed to
by Adam Stokes
Rather than relying on the correct comments/spaces etc in previous
versions go ahead and put everything in a separate uninstall batch
file. Make sure we force terminate any lingering matahari process and
finally continue on with the removal of matahari.
Some other minor fixes as a result (updated project page in cpack
setting, etc)
Signed-off-by: Adam Stokes <astokes(a)fedoraproject.org>
---
CMakeLists.txt | 16 +++-------------
src/windows/install.bat | 14 ++++++++------
src/windows/uninstall.bat | 21 +++++++++++++++++++++
3 files changed, 32 insertions(+), 19 deletions(-)
create mode 100644 src/windows/uninstall.bat
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 256ceba..4a00c47 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,7 +49,7 @@ if(WIN32)
set (CPACK_NSIS_MUI_ICON "${CMAKE_CURRENT_SOURCE_DIR}/src/windows/matahari-icon.ico")
set (CPACK_NSIS_MUI_UNIICON "${CMAKE_CURRENT_SOURCE_DIR}/src/windows/matahari-icon.ico")
set (CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/src/windows/matahari-install-banner.bmp")
- set (CPACK_NSIS_URL_INFO_ABOUT "http://fedorahosted.org/matahari")
+ set (CPACK_NSIS_URL_INFO_ABOUT "http://matahariproject.org")
# Needs this to correctly set up Start menu links later.
set (CPACK_PACKAGE_EXECUTABLES "")
@@ -72,18 +72,7 @@ if(WIN32)
set( CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "\\n")
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_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_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_netd.exe\\\"'\\n"
- " Some comment\\n ExecWait 'del \\\"$INSTDIR\\\\mh_serviced.exe\\\"'\\n"
+ " Some comment\\n ExecWait \\\"$INSTDIR\\\\sbin\\\\uninstall.bat\\\"\\n"
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/windows/autorun.inf.in
@@ -103,6 +92,7 @@ if(WIN32)
file(GLOB_RECURSE SRVANY_EXE ${MINGW_ROOT}/*/srvany.exe)
install(FILES ${SRVANY_EXE} DESTINATION sbin)
install(FILES src/windows/install.bat DESTINATION sbin)
+ install(FILES src/windows/uninstall.bat DESTINATION sbin)
else(WIN32)
diff --git a/src/windows/install.bat b/src/windows/install.bat
index 5e6307e..3b0224b 100644
--- a/src/windows/install.bat
+++ b/src/windows/install.bat
@@ -12,12 +12,14 @@ cd "%target%"
rem Now install the agents as services and start them
-set agents=hostd 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
-for %%A in (%agents%) do mh_%%A.exe install "%target%\matahari-qmf-%%A.exe" "%target%"
-for %%A in (%agents%) do sc start mh_%%A
+set agents=hostd networkd serviced sysconfigd
+for %%A in (%agents%) do (
+ sc delete mh_%%A
+ del mh_%%A.exe
+ copy srvany.exe mh_%%A.exe
+ mh_%%A.exe install "%target%\matahari-qmf-%%A.exe" "%target%"
+ sc start mh_%%A
+)
rem Remove the old name for the network agent
sc delete mh_netd
diff --git a/src/windows/uninstall.bat b/src/windows/uninstall.bat
new file mode 100644
index 0000000..d24a958
--- /dev/null
+++ b/src/windows/uninstall.bat
@@ -0,0 +1,21 @@
+rem UnInstall Matahari services
+echo
+
+rem Get the install directory
+set target=%0
+set target=%target:\uninstall.bat=%
+
+rem Now remove quotes so we can add them as necessary
+set target=%target:"=%
+
+cd "%target%"
+
+rem Now uninstall the agents
+
+set agents=hostd networkd serviced sysconfigd
+for %%A in (%agents%) do (
+ sc stop mh_%%A
+ sc delete mh_%%A
+ taskkill /IM matahari-qmf-%%A.exe /f
+ del mh_%%A.exe
+)
--
1.7.6.4
12 years, 7 months
[PATCH 0/5] Get Matahari building on Ubuntu.
by Russell Bryant
Greetings,
This set of patches includes the changes I made to get Matahari successfully
built and running on Ubuntu Server 10.04 (Lucid). Here are some notes about
how I did it.
I started with a minimal install. On top of that, I installed these packages:
gcc, g++, autoconf, cmake, make, python-software-properties, git-core,
git-email, openssh-server, libpcre3-dev, pkg-config, uuid-dev,
libglib2.0-dev, libcurl4-openssl-dev, libaugeas-dev, libdbus-glib-1-dev,
libpolkit-gobject-1-dev, libnss3-dev, xsltproc
There are no official qpid packages. However, there are some in a PPA that
I used.
https://launchpad.net/~kb3gtn/+archive/qpid
To add this PPA to the system and install qpid:
$ sudo add-apt-repository ppa:kb3gtn/qpid
$ sudo apt-get install qpid-cpp qpid-qmf qpid-python qpid-tools
The sigar library is also not available. We can include this in the
Matahari PPA. For now you just have to install it manually. This
is what I did:
$ wget http://sourceforge.net/projects/sigar/files/sigar/1.6/hyperic-sigar-1.6.3...
$ tar xvzf hyperic-sigar-1.6.3.tar.gz
$ cd hyperic-sigar-1.6.3
$ sudo cp sigar-bin/include/*.h /usr/include
$ sudo cp sigar-bin/lib/libsigar-amd64-linux.so /usr/lib/libsigar.so
$ sudo ldconfig
The final issue I hit was that the qmfgen Python lib gets installed into
/usr/lib64/python2.6/site-packages/, but this was not in the Python PATH.
So, to get qmf-gen to work so the Matahari build can use it:
$ export PYTHONPATH=/usr/lib64/python2.6/site-packages
>From here I just cloned matahari and built it as usual. The only thing
I have checked so far is I manually ran one of the agents in the build
dir and verified that it appeared to run correctly.
Some high level next steps:
1) Get a source based "make install" working for Matahari
2) Package sigar in the Matahari PPA
3) Package Matahari in the Matahari PPA after #1 works
[PATCH 1/5] build: Don't assume rpm is available.
[PATCH 2/5] dnssrv: Include utilities.h for g_list_free_full().
[PATCH 3/5] sysconfig: Make augeas support optional.
[PATCH 4/5] dbus: Resolve format string compiler warnings.
[PATCH 5/5] services: resolve asprintf() compiler warnings.
GNUmakefile | 5 +++++
src/CMakeLists.txt | 10 ++++++----
src/include/config.h.in | 1 +
src/lib/dnssrv_linux.c | 1 +
src/lib/mh_dbus_common.c | 8 ++++----
src/lib/services.c | 19 +++++++++++++++----
src/lib/services_linux.c | 4 +++-
src/lib/sysconfig_linux.c | 11 +++++++++++
src/service/service-dbus.c | 8 ++++----
src/sysconfig/sysconfig-dbus.c | 4 ++--
10 files changed, 52 insertions(+), 19 deletions(-)
Thanks,
--
Russell Bryant
12 years, 7 months