Sysconfig agent v4
by Adam Stokes
This patch adds additional support for key getter/setter when verifying if a system
has been configured or not. Along with the inclusions of recent reviewers.
12 years, 9 months
[PATCH] - Sysconfig agent v5
by Adam Stokes
- Moved public routines into main sysconfig.c file
and called os dependent routines from there
- make run_uri, run_string verify system configured status
Signed-off-by: Adam Stokes <astokes(a)fedoraproject.org>
---
src/CMakeLists.txt | 2 +-
src/include/matahari/sysconfig.h | 97 +++++++++++++++++++++
src/lib/CMakeLists.txt | 17 ++--
src/lib/sysconfig.c | 105 +++++++++++++++++++++++
src/lib/sysconfig_linux.c | 160 +++++++++++++++++++++++++++++++++++
src/lib/sysconfig_private.h | 33 +++++++
src/lib/sysconfig_windows.c | 48 +++++++++++
src/sysconfig/CMakeLists.txt | 30 +++++++
src/sysconfig/schema.xml | 35 ++++++++
src/sysconfig/sysconfig-console.cpp | 97 +++++++++++++++++++++
src/sysconfig/sysconfig-qmf.cpp | 142 +++++++++++++++++++++++++++++++
src/tests/CMakeLists.txt | 6 +-
src/tests/mh_api_sysconfig.h | 37 ++++++++
13 files changed, 797 insertions(+), 12 deletions(-)
create mode 100644 src/include/matahari/sysconfig.h
create mode 100644 src/lib/sysconfig.c
create mode 100644 src/lib/sysconfig_linux.c
create mode 100644 src/lib/sysconfig_private.h
create mode 100644 src/lib/sysconfig_windows.c
create mode 100644 src/sysconfig/CMakeLists.txt
create mode 100644 src/sysconfig/schema.xml
create mode 100644 src/sysconfig/sysconfig-console.cpp
create mode 100644 src/sysconfig/sysconfig-qmf.cpp
create mode 100644 src/tests/mh_api_sysconfig.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2bb99bd..9acb60c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -141,7 +141,7 @@ add_subdirectory(lib)
add_subdirectory(host)
add_subdirectory(network)
add_subdirectory(service)
-add_subdirectory(postboot)
+add_subdirectory(sysconfig)
add_subdirectory(tests)
### Installation
diff --git a/src/include/matahari/sysconfig.h b/src/include/matahari/sysconfig.h
new file mode 100644
index 0000000..4af136a
--- /dev/null
+++ b/src/include/matahari/sysconfig.h
@@ -0,0 +1,97 @@
+/* sysconfig.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 Config API
+ * \ingroup coreapi
+ */
+
+#ifndef __MH_SYSCONFIG_H__
+#define __MH_SYSCONFIG_H__
+
+#include <stdint.h>
+#include <glib.h>
+/*! Supported FLAGS */
+#define MH_SYSCONFIG_FLAG_FORCE (1 << 0)
+
+/**
+ * Download and process URI for configuration
+ *
+ * \param[in] uri the url of configuration item
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ * \param[in] key configuration key for keeping track of existing
+ * configuration runs
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern int mh_sysconfig_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key);
+
+/**
+ * Process a text blob
+ *
+ * \param[in] string the text blob to process, accepts a range of data from XML to Puppet classes
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ * \param[in] key configuration key for keeping track of existing
+ * configuration runs
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern int mh_sysconfig_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key);
+
+/**
+ * Query against a configuration object on the system
+ *
+ * \param[in] query the query command used
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern const char *
+mh_sysconfig_query(const char *query, uint32_t flags, const char *scheme);
+
+/**
+ * Set system as configured
+ *
+ * \param[in] key config item to define
+ *
+ * \return TRUE if applying key to config succeeds
+ */
+extern gboolean
+mh_sysconfig_set_configured(const char *key);
+
+/**
+ * Test if system has been configured
+ *
+ * \param[in] flags allow a force reconfiguration
+ * \param[in] key config item to test if used
+ *
+ * \return TRUE if system is configured
+ */
+extern gboolean
+mh_sysconfig_is_configured(const char *key);
+
+#endif // __MH_SYSCONFIG_H__
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index a8bdddf..7548b78 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -1,10 +1,10 @@
# Library
-set(LIBS mcommon mhost mnetwork mservice mpostboot)
+set(LIBS mcommon mhost mnetwork mservice msysconfig)
include_directories(${pcre_INCLUDE_DIRS})
# See http://sourceware.org/autobook/autobook/autobook_91.html for
-# how to set the library version appropriately
+# how to set the library version appropriately
add_library (mcommon SHARED utilities.c mainloop.c dnssrv_${VARIANT}.c)
set_target_properties(mcommon PROPERTIES SOVERSION 1.0.0)
@@ -26,18 +26,19 @@ 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})
-add_library (mpostboot SHARED postboot.c)
-set_target_properties(mpostboot PROPERTIES SOVERSION 1.0.0)
-target_link_libraries(mpostboot ${pcre_LIBRARIES} mcommon ${glib_LIBRARIES})
+add_library (msysconfig SHARED sysconfig.c sysconfig_${VARIANT}.c)
+set_target_properties(msysconfig PROPERTIES SOVERSION 1.0.0)
+target_link_libraries(msysconfig ${pcre_LIBRARIES} mcommon ${glib_LIBRARIES})
if(WIN32)
foreach (lib ${LIBS})
- target_link_libraries(${lib} wsock32)
- install(TARGETS ${lib} DESTINATION sbin)
+ target_link_libraries(${lib} wsock32 dnsapi)
+ install(TARGETS ${lib} DESTINATION sbin)
endforeach (lib ${LIBS})
else(WIN32)
foreach (lib ${LIBS})
- install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX})
+ target_link_libraries(${lib} curl)
+ install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX})
endforeach (lib ${LIBS})
endif(WIN32)
diff --git a/src/lib/sysconfig.c b/src/lib/sysconfig.c
new file mode 100644
index 0000000..5e19230
--- /dev/null
+++ b/src/lib/sysconfig.c
@@ -0,0 +1,105 @@
+/* sysconfig.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
+
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "matahari/utilities.h"
+#include "sysconfig_private.h"
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+#ifdef WIN32
+static const char keys_dir[] = "c:\\";
+#else
+static const char keys_dir[] = "/var/lib/matahari/";
+#endif
+
+static gboolean
+set_key(const char *key)
+{
+ char key_file[PATH_MAX];
+ const char contents[] = "1";
+
+ g_snprintf(key_file, sizeof(key_file), "%s%s", keys_dir, key);
+ if (!g_file_set_contents(key_file, contents, strlen(contents), NULL)) {
+ mh_err("Could not set file %s", key_file);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+get_key(const char *key)
+{
+ char key_file[PATH_MAX];
+ char *contents;
+ size_t length;
+
+ g_snprintf(key_file, sizeof(key_file), "%s%s", keys_dir, key);
+ if (g_file_test(key_file, G_FILE_TEST_EXISTS)) {
+ g_file_get_contents(key_file, &contents, &length, NULL);
+ if ((strcmp(contents, "1")) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+gboolean
+mh_sysconfig_set_configured(const char *key)
+{
+ if (!set_key(key)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean
+mh_sysconfig_is_configured(const char *key)
+{
+ if (!get_key(key)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int
+mh_sysconfig_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key) {
+ return sysconfig_os_run_uri(uri, flags, scheme, key);
+}
+
+int
+mh_sysconfig_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key) {
+ return sysconfig_os_run_string(string, flags, scheme, key);
+}
+
+const char *
+mh_sysconfig_query(const char *query, uint32_t flags, const char *scheme) {
+ return sysconfig_os_query(query, flags, scheme);
+}
diff --git a/src/lib/sysconfig_linux.c b/src/lib/sysconfig_linux.c
new file mode 100644
index 0000000..3f99233
--- /dev/null
+++ b/src/lib/sysconfig_linux.c
@@ -0,0 +1,160 @@
+/* sysconfig_linux.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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"
+#include <stddef.h>
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <curl/curl.h>
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "matahari/utilities.h"
+#include "sysconfig_private.h"
+
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+static int
+sysconfig_os_download(const char *uri, FILE *fp)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ curl = curl_easy_init();
+ if (curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, uri);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+ res = curl_easy_perform(curl);
+
+ if (CURLE_OK != res) {
+ return -1;
+ }
+ }
+ curl_global_cleanup();
+ return 0;
+}
+
+
+static int
+sysconfig_os_run_puppet(const char *uri, const char *data)
+{
+ gboolean ret;
+ GError *error;
+ char filename[PATH_MAX + 1];
+ gchar cmd[PATH_MAX];
+ int fd;
+ FILE *fp;
+
+ if (uri != NULL) {
+ strncpy(filename, "puppet_conf_XXXXXX", sizeof(filename) -1);
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ return -1;
+ }
+ fp = fdopen(fd, "w+b");
+ if (fp == NULL) {
+ fclose(fp);
+ return -1;
+ }
+ if ((sysconfig_os_download(uri, fp)) != 0) {
+ fclose(fp);
+ return -1;
+ }
+ fclose(fp);
+ } else if (data != NULL) {
+ strncpy(filename,"puppet_conf_blob", sizeof(filename) -1);
+ g_file_set_contents(filename, data, strlen(data), NULL);
+ } else {
+ return -1;
+ }
+
+ g_snprintf(cmd, sizeof(cmd), "puppet %s", filename);
+ ret = g_spawn_async(NULL, (gchar **)cmd, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ fprintf(stderr, "bool: %d", ret);
+ if (ret == FALSE) {
+ g_error_free(error);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+sysconfig_os_run_augeas(const char *query, const char *data)
+{
+ mh_warn("not implemented\n");
+ return 0;
+}
+
+static const char *
+sysconfig_os_query_augeas(const char *query)
+{
+ const char *data = NULL;
+ mh_warn("not implemented\n");
+ return data;
+}
+
+int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ int rc = 0;
+
+ if (mh_sysconfig_is_configured(key) == FALSE || (flags & MH_SYSCONFIG_FLAG_FORCE)) {
+ if (strcasecmp(scheme, "puppet") == 0) {
+ rc = sysconfig_os_run_puppet(uri, NULL);
+ } else {
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+int
+sysconfig_os_run_string(const char *data, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ int rc = 0;
+
+ if (mh_sysconfig_is_configured(key) == FALSE || (flags & MH_SYSCONFIG_FLAG_FORCE)) {
+ if (strcasecmp(scheme, "puppet") == 0) {
+ rc = sysconfig_os_run_puppet(NULL, data);
+ } else {
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme)
+{
+ const char *data = NULL;
+
+ if (strcasecmp(scheme, "augeas") == 0) {
+ data = sysconfig_os_query_augeas(query);
+ }
+
+ return data;
+}
diff --git a/src/lib/sysconfig_private.h b/src/lib/sysconfig_private.h
new file mode 100644
index 0000000..f521ad4
--- /dev/null
+++ b/src/lib/sysconfig_private.h
@@ -0,0 +1,33 @@
+/* sysconfig_private.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 __MH_SYSCONFIG_PRIVATE_H_
+#define __MH_SYSCONFIG_PRIVATE_H_
+
+extern int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key);
+
+extern int
+sysconfig_os_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key);
+
+extern const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme);
+
+#endif /* __MH_SYSCONFIG_PRIVATE_H_ */
diff --git a/src/lib/sysconfig_windows.c b/src/lib/sysconfig_windows.c
new file mode 100644
index 0000000..187a7e8
--- /dev/null
+++ b/src/lib/sysconfig_windows.c
@@ -0,0 +1,48 @@
+/* sysconfig_windows.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <glib.h>
+
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "sysconfig_private.h"
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key)
+{
+
+ return 0;
+}
+
+int
+sysconfig_os_run_string(const char *data, uint32_t flags, const char *scheme,
+ const char *key)
+{
+
+ return 0;
+}
+
+const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme)
+{
+ const char *data = NULL;
+ return data;
+}
diff --git a/src/sysconfig/CMakeLists.txt b/src/sysconfig/CMakeLists.txt
new file mode 100644
index 0000000..1d9fba8
--- /dev/null
+++ b/src/sysconfig/CMakeLists.txt
@@ -0,0 +1,30 @@
+set(BASE "sysconfig")
+set(BASE_LIB "m${BASE}")
+set(QMF_AGENT "matahari-qmf-${BASE}d")
+set(QMF_CONSOLE "matahari-qmf-${BASE}-consoled")
+
+# 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})
+ add_executable(${QMF_CONSOLE} ${BASE}-console.cpp)
+
+ target_link_libraries(${QMF_AGENT} ${BASE_LIB} mcommon_qmf)
+ target_link_libraries(${QMF_CONSOLE} mcommon_qmf)
+
+ if(NOT WIN32)
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ # Override BASE for matahari-sysconfig-console
+ unset(BASE)
+ set(BASE "sysconfig-console")
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ endif(NOT WIN32)
+
+ install(TARGETS ${QMF_AGENT} DESTINATION sbin)
+ install(TARGETS ${QMF_CONSOLE} DESTINATION sbin)
+endif(WITH-QMF)
diff --git a/src/sysconfig/schema.xml b/src/sysconfig/schema.xml
new file mode 100644
index 0000000..d5c52aa
--- /dev/null
+++ b/src/sysconfig/schema.xml
@@ -0,0 +1,35 @@
+<schema package="org.matahariproject">
+
+ <!-- Config API -->
+ <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="is_postboot_configured" type="uint32" access="RO" desc="Check if agent is configured." />
+
+ <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="scheme" dir="I" type="sstr" />
+ <arg name="key" dir="I" type="sstr" />
+ <arg name="flags" dir="I" type="uint32" />
+ </method>
+
+ <method name="run_string" desc="Send configure text method">
+ <arg name="text" dir="I" type="sstr" />
+ <arg name="scheme" dir="I" type="sstr" />
+ <arg name="key" dir="I" type="sstr" />
+ <arg name="flags" dir="I" type="uint32" />
+ </method>
+
+ <method name="query" desc="Perform query lookup">
+ <arg name="text" dir="I" type="sstr" />
+ <arg name="scheme" dir="I" type="sstr" />
+ <arg name="flags" dir="I" type="uint32" />
+ </method>
+
+ <method name="is_configured" desc="Check if system is configured">
+ <arg name="key" dir="I" type="sstr" />
+ </method>
+ </class>
+</schema>
diff --git a/src/sysconfig/sysconfig-console.cpp b/src/sysconfig/sysconfig-console.cpp
new file mode 100644
index 0000000..ac40fb8
--- /dev/null
+++ b/src/sysconfig/sysconfig-console.cpp
@@ -0,0 +1,97 @@
+/* config-console.cpp - Copyright (c) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include <qpid/messaging/Connection.h>
+#include <qpid/messaging/Duration.h>
+#include <qmf/ConsoleSession.h>
+#include <qmf/ConsoleEvent.h>
+#include <qmf/Agent.h>
+#include <qmf/Data.h>
+#include <qmf/DataAddr.h>
+#include <qmf/Query.h>
+#include <qpid/types/Variant.h>
+
+#include "matahari/agent.h"
+
+#include <string>
+#include <iostream>
+#include <sstream>
+
+extern "C" {
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+}
+
+using namespace std;
+using namespace qmf;
+using qpid::types::Variant;
+using qpid::messaging::Duration;
+
+int main(int argc, char **argv)
+{
+ qpid::types::Variant::Map options;
+ qpid::types::Variant::Map callOptions;
+ string sessionOptions;
+ ConsoleEvent event;
+ Agent agent;
+
+ mh_log_init("sysconfig-console", LOG_TRACE, TRUE);
+
+ mh_add_option('U', required_argument, "uri", "URI of configuration", &options, NULL);
+
+ qpid::types::Variant::Map urlMap = mh_parse_options("sysconfig-console", argc, argv, options);
+
+ callOptions["uri"] = options["uri"];
+
+ mh_log_init("sysconfig-console", mh_log_level, mh_log_level > LOG_INFO);
+
+ qpid::messaging::Connection connection(urlMap["uri"], options);
+ connection.open();
+
+ ConsoleSession session(connection, sessionOptions);
+ // Only filter connecting agents under matahariproject.org vendor and Config product
+ session.setAgentFilter("[and, [eq, _vendor, [quote, 'matahariproject.org']], [eq, _product, [quote, 'Sysconfig']]]");
+ session.open();
+
+ while(session.getAgentCount() == 0) {
+ g_usleep(1000);
+ }
+
+ while (true) {
+ if(session.nextEvent(event)) {
+ switch(event.getType()) {
+ case CONSOLE_AGENT_ADD:
+ {
+ agent = event.getAgent();
+ DataAddr agent_event_addr("config", agent.getName(), 0);
+ ConsoleEvent result(agent.callMethod("run_uri",
+ callOptions,
+ agent_event_addr));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/src/sysconfig/sysconfig-qmf.cpp b/src/sysconfig/sysconfig-qmf.cpp
new file mode 100644
index 0000000..01d6c10
--- /dev/null
+++ b/src/sysconfig/sysconfig-qmf.cpp
@@ -0,0 +1,142 @@
+/* sysconfig-qmf.cpp - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 Sysconfig QMF Agent
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include "matahari/agent.h"
+
+#include "qmf/org/matahariproject/QmfPackage.h"
+
+#include <qpid/agent/ManagementAgent.h>
+
+extern "C" {
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
+#include "matahari/sysconfig.h"
+#include "matahari/logging.h"
+#include "matahari/network.h"
+#include "matahari/host.h"
+#include <sigar.h>
+#include <sigar_format.h>
+};
+
+class ConfigAgent : public MatahariAgent
+{
+private:
+ qmf::org::matahariproject::PackageDefinition _package;
+ qmf::Data _instance;
+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)
+{
+ ConfigAgent agent;
+ int rc = agent.init(argc, argv, "Sysconfig");
+ if (rc == 0) {
+ agent.run();
+ }
+ return rc;
+}
+
+int
+ConfigAgent::setup(qmf::AgentSession session)
+{
+ _package.configure(session);
+ _instance = qmf::Data(_package.data_Sysconfig);
+
+ _instance.setProperty("hostname", mh_hostname());
+ _instance.setProperty("uuid", mh_uuid());
+ _instance.setProperty("is_postboot_configured", 0);
+
+ session.addData(_instance, "sysconfig");
+ return 0;
+}
+
+gboolean
+ConfigAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event, gpointer user_data)
+{
+ int rc = 0;
+ uint32_t flags;
+
+ const std::string& methodName(event.getMethodName());
+ if (event.getType() != qmf::AGENT_METHOD) {
+ return TRUE;
+ }
+
+ qpid::types::Variant::Map& args = event.getArguments();
+
+ if (methodName == "run_uri") {
+ flags = args["flags"].asUint32();
+ if((mh_sysconfig_is_configured(args["key"].asString().c_str())) == 0) {
+ rc = mh_sysconfig_run_uri(args["uri"].asString().c_str(),
+ flags,
+ args["scheme"].asString().c_str(),
+ args["key"].asString().c_str());
+ if (rc == 0) {
+ mh_sysconfig_set_configured(args["key"].asString().c_str());
+ }
+ }
+ event.addReturnArgument("configured", rc);
+ } else if (methodName == "run_string") {
+ flags = args["flags"].asUint32();
+ if((mh_sysconfig_is_configured(args["key"].asString().c_str())) == 0) {
+ rc = mh_sysconfig_run_string(args["data"].asString().c_str(),
+ flags,
+ args["scheme"].asString().c_str(),
+ args["key"].asString().c_str());
+ if (rc == 0) {
+ mh_sysconfig_set_configured(args["key"].asString().c_str());
+ }
+ }
+ event.addReturnArgument("configured", rc);
+ } else if (methodName == "query") {
+ flags = args["flags"].asUint32();
+ const char *data = NULL;
+ data = mh_sysconfig_query(args["query"].asString().c_str(),
+ flags,
+ args["scheme"].asString().c_str());
+ event.addReturnArgument("query", data);
+ } else if (methodName == "is_configured") {
+ rc = mh_sysconfig_is_configured(args["key"].asString().c_str());
+ _instance.setProperty("is_postboot_configured", rc);
+ event.addReturnArgument("configured", rc);
+ } else {
+ session.raiseException(event, MH_NOT_IMPLEMENTED);
+ goto bail;
+ }
+
+ session.methodSuccess(event);
+
+bail:
+ return TRUE;
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 6db157c..8fe81f2 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -5,13 +5,13 @@ if(CXXTEST_FOUND)
ENABLE_TESTING()
CXXTEST_ADD_TEST(mh_api_network_unittest network_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_network.h)
CXXTEST_ADD_TEST(mh_api_host_unittest host_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_host.h)
- CXXTEST_ADD_TEST(mh_api_postboot_unittest postboot_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_postboot.h)
+ CXXTEST_ADD_TEST(mh_api_sysconfig_unittest sysconfig_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_sysconfig.h)
CXXTEST_ADD_TEST(mh_hsa_unittest hsa_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_hsa_${VARIANT}.h)
add_library(mh_tester SHARED test_utilities.c)
- target_link_libraries(mh_tester ${pcre_LIBRARIES} mcommon mnetwork mhost mpostboot)
+ target_link_libraries(mh_tester ${pcre_LIBRARIES} mcommon mnetwork mhost msysconfig)
target_link_libraries(mh_api_network_unittest mh_tester)
target_link_libraries(mh_api_host_unittest mh_tester)
- target_link_libraries(mh_api_postboot_unittest mh_tester)
+ target_link_libraries(mh_api_sysconfig_unittest mh_tester)
target_link_libraries(mh_hsa_unittest mh_tester)
endif(CXXTEST_FOUND)
diff --git a/src/tests/mh_api_sysconfig.h b/src/tests/mh_api_sysconfig.h
new file mode 100644
index 0000000..3551771
--- /dev/null
+++ b/src/tests/mh_api_sysconfig.h
@@ -0,0 +1,37 @@
+#ifndef __MH_API_NETWORK_UNITTEST_H
+#define __MH_API_NETWORK_UNITTEST_H
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <vector>
+#include <cstdlib>
+#include <cstdio>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <cxxtest/TestSuite.h>
+
+extern "C" {
+#include "matahari/sysconfig.h"
+#include <glib.h>
+#include "mh_test_utilities.h"
+};
+
+using namespace std;
+
+class MhApiSysconfigSuite : public CxxTest::TestSuite
+{
+ public:
+
+ void testIsConfigured(void)
+ {
+ const char *uri = "http://matahariproject.org/atom.xml"; // Test if download succeeds
+ uint32_t flags = 0;
+ const char key[] = "org.matahariproject.firstboot"; // Unimportant key defined
+ TS_ASSERT((mh_sysconfig_set_configured(key)) == TRUE);
+ TS_ASSERT((mh_sysconfig_is_configured(key)) == TRUE);
+ TS_ASSERT((mh_sysconfig_run_uri(uri, flags, "puppet", key)) != -1);
+ }
+};
+
+#endif
--
1.7.6
12 years, 9 months
[PATCH] - Sysconfig agent v7
by Adam Stokes
- Final review of all changes posted via ML
Signed-off-by: Adam Stokes <astokes(a)fedoraproject.org>
---
src/CMakeLists.txt | 2 +-
src/include/matahari/sysconfig.h | 97 +++++++++++++++++++++
src/lib/CMakeLists.txt | 14 ++--
src/lib/sysconfig.c | 108 +++++++++++++++++++++++
src/lib/sysconfig_linux.c | 164 +++++++++++++++++++++++++++++++++++
src/lib/sysconfig_private.h | 33 +++++++
src/lib/sysconfig_windows.c | 74 ++++++++++++++++
src/sysconfig/CMakeLists.txt | 30 +++++++
src/sysconfig/schema.xml | 39 ++++++++
src/sysconfig/sysconfig-console.cpp | 97 +++++++++++++++++++++
src/sysconfig/sysconfig-qmf.cpp | 123 ++++++++++++++++++++++++++
src/tests/CMakeLists.txt | 6 +-
src/tests/mh_api_sysconfig.h | 37 ++++++++
13 files changed, 813 insertions(+), 11 deletions(-)
create mode 100644 src/include/matahari/sysconfig.h
create mode 100644 src/lib/sysconfig.c
create mode 100644 src/lib/sysconfig_linux.c
create mode 100644 src/lib/sysconfig_private.h
create mode 100644 src/lib/sysconfig_windows.c
create mode 100644 src/sysconfig/CMakeLists.txt
create mode 100644 src/sysconfig/schema.xml
create mode 100644 src/sysconfig/sysconfig-console.cpp
create mode 100644 src/sysconfig/sysconfig-qmf.cpp
create mode 100644 src/tests/mh_api_sysconfig.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8691684..3bb0294 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -147,7 +147,7 @@ add_subdirectory(lib)
add_subdirectory(host)
add_subdirectory(network)
add_subdirectory(service)
-add_subdirectory(postboot)
+add_subdirectory(sysconfig)
add_subdirectory(tests)
### Installation
diff --git a/src/include/matahari/sysconfig.h b/src/include/matahari/sysconfig.h
new file mode 100644
index 0000000..aced3b4
--- /dev/null
+++ b/src/include/matahari/sysconfig.h
@@ -0,0 +1,97 @@
+/* sysconfig.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 Config API
+ * \ingroup coreapi
+ */
+
+#ifndef __MH_SYSCONFIG_H__
+#define __MH_SYSCONFIG_H__
+
+#include <stdint.h>
+#include <glib.h>
+/*! Supported FLAGS */
+#define MH_SYSCONFIG_FLAG_FORCE (1 << 0)
+
+/**
+ * Download and process URI for configuration
+ *
+ * \param[in] uri the url of configuration item
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ * \param[in] key configuration key for keeping track of existing
+ * configuration runs
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern int
+mh_sysconfig_run_uri(const char *uri, uint32_t flags, const char *scheme, const char *key);
+
+/**
+ * Process a text blob
+ *
+ * \param[in] string the text blob to process, accepts a range of data from XML to Puppet classes
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ * \param[in] key configuration key for keeping track of existing
+ * configuration runs
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern int
+mh_sysconfig_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key);
+
+/**
+ * Query against a configuration object on the system
+ *
+ * \param[in] query the query command used
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ *
+ * \return DATA of returned query result
+ */
+extern const char *
+mh_sysconfig_query(const char *query, uint32_t flags, const char *scheme);
+
+/**
+ * Set system as configured
+ *
+ * \param[in] key config item to define
+ *
+ * \return TRUE if applying key to config succeeds
+ */
+extern gboolean
+mh_sysconfig_set_configured(const char *key);
+
+/**
+ * Test if system has been configured
+ *
+ * \param[in] flags allow a force reconfiguration
+ * \param[in] key config item to test if used
+ *
+ * \return TRUE if system is configured
+ */
+extern gboolean
+mh_sysconfig_is_configured(const char *key);
+
+#endif // __MH_SYSCONFIG_H__
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index a8bdddf..601d8cb 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -1,6 +1,6 @@
# Library
-set(LIBS mcommon mhost mnetwork mservice mpostboot)
+set(LIBS mcommon mhost mnetwork mservice msysconfig)
include_directories(${pcre_INCLUDE_DIRS})
# See http://sourceware.org/autobook/autobook/autobook_91.html for
@@ -26,18 +26,18 @@ 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})
-add_library (mpostboot SHARED postboot.c)
-set_target_properties(mpostboot PROPERTIES SOVERSION 1.0.0)
-target_link_libraries(mpostboot ${pcre_LIBRARIES} mcommon ${glib_LIBRARIES})
+add_library (msysconfig SHARED sysconfig.c sysconfig_${VARIANT}.c)
+set_target_properties(msysconfig PROPERTIES SOVERSION 1.0.0)
+target_link_libraries(msysconfig ${pcre_LIBRARIES} mcommon ${glib_LIBRARIES})
if(WIN32)
foreach (lib ${LIBS})
- target_link_libraries(${lib} wsock32)
- install(TARGETS ${lib} DESTINATION sbin)
+ target_link_libraries(${lib} wsock32 dnsapi)
+ install(TARGETS ${lib} DESTINATION sbin)
endforeach (lib ${LIBS})
else(WIN32)
foreach (lib ${LIBS})
- install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX})
+ install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX} curl)
endforeach (lib ${LIBS})
endif(WIN32)
diff --git a/src/lib/sysconfig.c b/src/lib/sysconfig.c
new file mode 100644
index 0000000..81d4ee9
--- /dev/null
+++ b/src/lib/sysconfig.c
@@ -0,0 +1,108 @@
+/* sysconfig.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
+
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "matahari/utilities.h"
+#include "sysconfig_private.h"
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+#ifdef WIN32
+static const char keys_dir[] = "c:\\";
+#else
+static const char keys_dir[] = "/var/lib/matahari/";
+#endif
+
+static gboolean
+set_key(const char *key)
+{
+ char key_file[PATH_MAX];
+ const char contents[] = "ok";
+
+ g_snprintf(key_file, sizeof(key_file), "%s%s", keys_dir, key);
+ if (!g_file_set_contents(key_file, contents, strlen(contents), NULL)) {
+ mh_err("Could not set file %s", key_file);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+get_key(const char *key)
+{
+ char key_file[PATH_MAX];
+ char *contents;
+ size_t length;
+
+ g_snprintf(key_file, sizeof(key_file), "%s%s", keys_dir, key);
+ if (g_file_test(key_file, G_FILE_TEST_EXISTS)) {
+ if(g_file_get_contents(key_file, &contents, &length, NULL)) {
+ if (strcmp(contents, "ok") == 0) {
+ free(contents);
+ return TRUE;
+ }
+ }
+ free(contents);
+ }
+ return FALSE;
+}
+
+gboolean
+mh_sysconfig_set_configured(const char *key)
+{
+ if (!set_key(key)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean
+mh_sysconfig_is_configured(const char *key)
+{
+ if (!get_key(key)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int
+mh_sysconfig_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key) {
+ return sysconfig_os_run_uri(uri, flags, scheme, key);
+}
+
+int
+mh_sysconfig_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key) {
+ return sysconfig_os_run_string(string, flags, scheme, key);
+}
+
+const char *
+mh_sysconfig_query(const char *query, uint32_t flags, const char *scheme) {
+ return sysconfig_os_query(query, flags, scheme);
+}
diff --git a/src/lib/sysconfig_linux.c b/src/lib/sysconfig_linux.c
new file mode 100644
index 0000000..62d8449
--- /dev/null
+++ b/src/lib/sysconfig_linux.c
@@ -0,0 +1,164 @@
+/* sysconfig_linux.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <glib.h>
+#include <curl/curl.h>
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "matahari/utilities.h"
+#include "sysconfig_private.h"
+
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+static int
+sysconfig_os_download(const char *uri, FILE *fp)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ curl = curl_easy_init();
+ if (curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, uri);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+ res = curl_easy_perform(curl);
+
+ if (CURLE_OK != res) {
+ return -1;
+ }
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return 0;
+}
+
+
+static int
+sysconfig_os_run_puppet(const char *uri, const char *data)
+{
+ gboolean ret;
+ GError *error = NULL;
+ gchar *cmd[3];
+ char *filename = NULL;
+ int fd;
+ FILE *fp;
+
+ if (uri != NULL) {
+ snprintf(filename, PATH_MAX, "%s", "puppet_conf_XXXXXX");
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ return -1;
+ }
+ fp = fdopen(fd, "w+b");
+ if (fp == NULL) {
+ close(fd);
+ return -1;
+ }
+ if ((sysconfig_os_download(uri, fp)) != 0) {
+ fclose(fp);
+ return -1;
+ }
+ fclose(fp);
+ } else if (data != NULL) {
+ snprintf(filename, PATH_MAX, "%s", "puppet_conf_blob");
+ g_file_set_contents(filename, data, strlen(data), NULL);
+ } else {
+ return -1;
+ }
+
+ cmd[0] = "puppet";
+ cmd[1] = filename;
+ cmd[2] = NULL;
+ mh_info("Running %s %s", cmd[0], cmd[1]);
+ ret = g_spawn_async(NULL, cmd, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (ret == FALSE) {
+ g_error_free(error);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+sysconfig_os_run_augeas(const char *query, const char *data)
+{
+ mh_warn("not implemented\n");
+ return 0;
+}
+
+static const char *
+sysconfig_os_query_augeas(const char *query)
+{
+ const char *data = NULL;
+ mh_warn("not implemented\n");
+ return data;
+}
+
+int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ int rc = 0;
+
+ if (mh_sysconfig_is_configured(key) == FALSE || (flags & MH_SYSCONFIG_FLAG_FORCE)) {
+ if (strcasecmp(scheme, "puppet") == 0) {
+ rc = sysconfig_os_run_puppet(uri, NULL);
+ } else {
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+int
+sysconfig_os_run_string(const char *data, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ int rc = 0;
+
+ if (mh_sysconfig_is_configured(key) == FALSE || (flags & MH_SYSCONFIG_FLAG_FORCE)) {
+ if (strcasecmp(scheme, "puppet") == 0) {
+ rc = sysconfig_os_run_puppet(NULL, data);
+ } else {
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme)
+{
+ const char *data = NULL;
+
+ if (strcasecmp(scheme, "augeas") == 0) {
+ data = sysconfig_os_query_augeas(query);
+ }
+
+ return data;
+}
diff --git a/src/lib/sysconfig_private.h b/src/lib/sysconfig_private.h
new file mode 100644
index 0000000..f521ad4
--- /dev/null
+++ b/src/lib/sysconfig_private.h
@@ -0,0 +1,33 @@
+/* sysconfig_private.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 __MH_SYSCONFIG_PRIVATE_H_
+#define __MH_SYSCONFIG_PRIVATE_H_
+
+extern int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key);
+
+extern int
+sysconfig_os_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key);
+
+extern const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme);
+
+#endif /* __MH_SYSCONFIG_PRIVATE_H_ */
diff --git a/src/lib/sysconfig_windows.c b/src/lib/sysconfig_windows.c
new file mode 100644
index 0000000..2b272e4
--- /dev/null
+++ b/src/lib/sysconfig_windows.c
@@ -0,0 +1,74 @@
+/* sysconfig_windows.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <windows.h>
+#include <glib.h>
+
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "sysconfig_private.h"
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+static int
+sysconfig_os_run_regedit(char *registry_file)
+{
+ gchar *cmd[4];
+ gboolean ret;
+ GError *error = NULL;
+
+ cmd[0] = "REGEDIT";
+ cmd[1] = "/S";
+ cmd[2] = registry_file;
+ cmd[3] = NULL;
+
+ ret = g_spawn_async(NULL, cmd, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (ret == FALSE) {
+ g_error_free(error);
+ return -1;
+ }
+ return 0;
+}
+
+int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ return 0;
+}
+
+int
+sysconfig_os_run_string(const char *data, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ char filename[PATH_MAX];
+ g_snprintf(filename, sizeof(filename), "%s\\%s.REG", g_getenv("TEMP"), key);
+ if (strcasecmp(scheme, "registry") == 0 ) {
+ g_file_set_contents(filename, data, strlen(data), NULL);
+ return sysconfig_os_run_regedit(filename);
+ }
+ return 0;
+}
+
+const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme)
+{
+ const char *data = NULL;
+ return data;
+}
diff --git a/src/sysconfig/CMakeLists.txt b/src/sysconfig/CMakeLists.txt
new file mode 100644
index 0000000..1d9fba8
--- /dev/null
+++ b/src/sysconfig/CMakeLists.txt
@@ -0,0 +1,30 @@
+set(BASE "sysconfig")
+set(BASE_LIB "m${BASE}")
+set(QMF_AGENT "matahari-qmf-${BASE}d")
+set(QMF_CONSOLE "matahari-qmf-${BASE}-consoled")
+
+# 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})
+ add_executable(${QMF_CONSOLE} ${BASE}-console.cpp)
+
+ target_link_libraries(${QMF_AGENT} ${BASE_LIB} mcommon_qmf)
+ target_link_libraries(${QMF_CONSOLE} mcommon_qmf)
+
+ if(NOT WIN32)
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ # Override BASE for matahari-sysconfig-console
+ unset(BASE)
+ set(BASE "sysconfig-console")
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ endif(NOT WIN32)
+
+ install(TARGETS ${QMF_AGENT} DESTINATION sbin)
+ install(TARGETS ${QMF_CONSOLE} DESTINATION sbin)
+endif(WITH-QMF)
diff --git a/src/sysconfig/schema.xml b/src/sysconfig/schema.xml
new file mode 100644
index 0000000..fa94bd5
--- /dev/null
+++ b/src/sysconfig/schema.xml
@@ -0,0 +1,39 @@
+<schema package="org.matahariproject">
+
+ <!-- Config API -->
+ <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="is_postboot_configured" type="uint32" access="RO" desc="Check if agent is configured." />
+
+ <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="uint32" />
+ </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="uint32" />
+ </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>
+
+ <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>
+ </class>
+</schema>
diff --git a/src/sysconfig/sysconfig-console.cpp b/src/sysconfig/sysconfig-console.cpp
new file mode 100644
index 0000000..ac40fb8
--- /dev/null
+++ b/src/sysconfig/sysconfig-console.cpp
@@ -0,0 +1,97 @@
+/* config-console.cpp - Copyright (c) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include <qpid/messaging/Connection.h>
+#include <qpid/messaging/Duration.h>
+#include <qmf/ConsoleSession.h>
+#include <qmf/ConsoleEvent.h>
+#include <qmf/Agent.h>
+#include <qmf/Data.h>
+#include <qmf/DataAddr.h>
+#include <qmf/Query.h>
+#include <qpid/types/Variant.h>
+
+#include "matahari/agent.h"
+
+#include <string>
+#include <iostream>
+#include <sstream>
+
+extern "C" {
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+}
+
+using namespace std;
+using namespace qmf;
+using qpid::types::Variant;
+using qpid::messaging::Duration;
+
+int main(int argc, char **argv)
+{
+ qpid::types::Variant::Map options;
+ qpid::types::Variant::Map callOptions;
+ string sessionOptions;
+ ConsoleEvent event;
+ Agent agent;
+
+ mh_log_init("sysconfig-console", LOG_TRACE, TRUE);
+
+ mh_add_option('U', required_argument, "uri", "URI of configuration", &options, NULL);
+
+ qpid::types::Variant::Map urlMap = mh_parse_options("sysconfig-console", argc, argv, options);
+
+ callOptions["uri"] = options["uri"];
+
+ mh_log_init("sysconfig-console", mh_log_level, mh_log_level > LOG_INFO);
+
+ qpid::messaging::Connection connection(urlMap["uri"], options);
+ connection.open();
+
+ ConsoleSession session(connection, sessionOptions);
+ // Only filter connecting agents under matahariproject.org vendor and Config product
+ session.setAgentFilter("[and, [eq, _vendor, [quote, 'matahariproject.org']], [eq, _product, [quote, 'Sysconfig']]]");
+ session.open();
+
+ while(session.getAgentCount() == 0) {
+ g_usleep(1000);
+ }
+
+ while (true) {
+ if(session.nextEvent(event)) {
+ switch(event.getType()) {
+ case CONSOLE_AGENT_ADD:
+ {
+ agent = event.getAgent();
+ DataAddr agent_event_addr("config", agent.getName(), 0);
+ ConsoleEvent result(agent.callMethod("run_uri",
+ callOptions,
+ agent_event_addr));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/src/sysconfig/sysconfig-qmf.cpp b/src/sysconfig/sysconfig-qmf.cpp
new file mode 100644
index 0000000..2e405f1
--- /dev/null
+++ b/src/sysconfig/sysconfig-qmf.cpp
@@ -0,0 +1,123 @@
+/* sysconfig-qmf.cpp - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 Sysconfig QMF Agent
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include <qpid/agent/ManagementAgent.h>
+#include "qmf/org/matahariproject/QmfPackage.h"
+#include "matahari/agent.h"
+
+extern "C" {
+#include "matahari/logging.h"
+#include "matahari/host.h"
+#include "matahari/sysconfig.h"
+};
+
+class ConfigAgent : public MatahariAgent
+{
+private:
+ qmf::org::matahariproject::PackageDefinition _package;
+ qmf::Data _instance;
+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)
+{
+ ConfigAgent agent;
+ int rc = agent.init(argc, argv, "Sysconfig");
+ if (rc == 0) {
+ agent.run();
+ }
+ return rc;
+}
+
+int
+ConfigAgent::setup(qmf::AgentSession session)
+{
+ _package.configure(session);
+ _instance = qmf::Data(_package.data_Sysconfig);
+
+ _instance.setProperty("hostname", mh_hostname());
+ _instance.setProperty("uuid", mh_uuid());
+ _instance.setProperty("is_postboot_configured", 0);
+
+ session.addData(_instance, "sysconfig");
+ return 0;
+}
+
+gboolean
+ConfigAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event, gpointer user_data)
+{
+ int rc = 0;
+
+ const std::string& methodName(event.getMethodName());
+ if (event.getType() != qmf::AGENT_METHOD) {
+ return TRUE;
+ }
+
+ qpid::types::Variant::Map& args = event.getArguments();
+
+ if (methodName == "run_uri") {
+ rc = mh_sysconfig_run_uri(args["uri"].asString().c_str(),
+ args["flags"].asUint32(),
+ args["scheme"].asString().c_str(),
+ args["key"].asString().c_str());
+ if (rc == 0) {
+ mh_sysconfig_set_configured(args["key"].asString().c_str());
+ }
+ event.addReturnArgument("status", rc);
+ } else if (methodName == "run_string") {
+ rc = mh_sysconfig_run_string(args["data"].asString().c_str(),
+ args["flags"].asUint32(),
+ args["scheme"].asString().c_str(),
+ args["key"].asString().c_str());
+ if (rc == 0) {
+ mh_sysconfig_set_configured(args["key"].asString().c_str());
+ }
+ event.addReturnArgument("status", rc);
+ } else if (methodName == "query") {
+ const char *data = NULL;
+ data = mh_sysconfig_query(args["query"].asString().c_str(),
+ args["flags"].asUint32(),
+ args["scheme"].asString().c_str());
+ event.addReturnArgument("query", data);
+ } else if (methodName == "is_configured") {
+ rc = mh_sysconfig_is_configured(args["key"].asString().c_str());
+ _instance.setProperty("is_postboot_configured", rc);
+ event.addReturnArgument("status", rc);
+ } else {
+ session.raiseException(event, MH_NOT_IMPLEMENTED);
+ goto bail;
+ }
+
+ session.methodSuccess(event);
+
+bail:
+ return TRUE;
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 6db157c..8fe81f2 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -5,13 +5,13 @@ if(CXXTEST_FOUND)
ENABLE_TESTING()
CXXTEST_ADD_TEST(mh_api_network_unittest network_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_network.h)
CXXTEST_ADD_TEST(mh_api_host_unittest host_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_host.h)
- CXXTEST_ADD_TEST(mh_api_postboot_unittest postboot_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_postboot.h)
+ CXXTEST_ADD_TEST(mh_api_sysconfig_unittest sysconfig_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_sysconfig.h)
CXXTEST_ADD_TEST(mh_hsa_unittest hsa_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_hsa_${VARIANT}.h)
add_library(mh_tester SHARED test_utilities.c)
- target_link_libraries(mh_tester ${pcre_LIBRARIES} mcommon mnetwork mhost mpostboot)
+ target_link_libraries(mh_tester ${pcre_LIBRARIES} mcommon mnetwork mhost msysconfig)
target_link_libraries(mh_api_network_unittest mh_tester)
target_link_libraries(mh_api_host_unittest mh_tester)
- target_link_libraries(mh_api_postboot_unittest mh_tester)
+ target_link_libraries(mh_api_sysconfig_unittest mh_tester)
target_link_libraries(mh_hsa_unittest mh_tester)
endif(CXXTEST_FOUND)
diff --git a/src/tests/mh_api_sysconfig.h b/src/tests/mh_api_sysconfig.h
new file mode 100644
index 0000000..9351aef
--- /dev/null
+++ b/src/tests/mh_api_sysconfig.h
@@ -0,0 +1,37 @@
+#ifndef __MH_API_NETWORK_UNITTEST_H
+#define __MH_API_NETWORK_UNITTEST_H
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <vector>
+#include <cstdlib>
+#include <cstdio>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <cxxtest/TestSuite.h>
+
+extern "C" {
+#include "matahari/sysconfig.h"
+#include <glib.h>
+#include "mh_test_utilities.h"
+};
+
+using namespace std;
+
+class MhApiSysconfigSuite : public CxxTest::TestSuite
+{
+ public:
+
+ void testIsConfigured(void)
+ {
+ const char *uri = "http://matahariproject.org/atom.xml"; // Test if download succeeds
+ const char flags = 0;
+ const char key[] = "org.matahariproject.test.unittest"; // Unimportant key defined
+ TS_ASSERT((mh_sysconfig_set_configured(key)) == TRUE);
+ TS_ASSERT((mh_sysconfig_is_configured(key)) == TRUE);
+ TS_ASSERT((mh_sysconfig_run_uri(uri, flags, "puppet", key)) != -1);
+ }
+};
+
+#endif
--
1.7.6
12 years, 9 months
[PATCH] - Sysconfig agent v6
by Adam Stokes
- Final review of all changes posted via ML
Signed-off-by: Adam Stokes <astokes(a)fedoraproject.org>
---
src/CMakeLists.txt | 2 +-
src/include/matahari/sysconfig.h | 98 +++++++++++++++++++++
src/lib/CMakeLists.txt | 14 ++--
src/lib/sysconfig.c | 106 ++++++++++++++++++++++
src/lib/sysconfig_linux.c | 164 +++++++++++++++++++++++++++++++++++
src/lib/sysconfig_private.h | 33 +++++++
src/lib/sysconfig_windows.c | 74 ++++++++++++++++
src/sysconfig/CMakeLists.txt | 30 +++++++
src/sysconfig/schema.xml | 39 ++++++++
src/sysconfig/sysconfig-console.cpp | 97 +++++++++++++++++++++
src/sysconfig/sysconfig-qmf.cpp | 123 ++++++++++++++++++++++++++
src/tests/CMakeLists.txt | 6 +-
src/tests/mh_api_sysconfig.h | 37 ++++++++
13 files changed, 812 insertions(+), 11 deletions(-)
create mode 100644 src/include/matahari/sysconfig.h
create mode 100644 src/lib/sysconfig.c
create mode 100644 src/lib/sysconfig_linux.c
create mode 100644 src/lib/sysconfig_private.h
create mode 100644 src/lib/sysconfig_windows.c
create mode 100644 src/sysconfig/CMakeLists.txt
create mode 100644 src/sysconfig/schema.xml
create mode 100644 src/sysconfig/sysconfig-console.cpp
create mode 100644 src/sysconfig/sysconfig-qmf.cpp
create mode 100644 src/tests/mh_api_sysconfig.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8691684..3bb0294 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -147,7 +147,7 @@ add_subdirectory(lib)
add_subdirectory(host)
add_subdirectory(network)
add_subdirectory(service)
-add_subdirectory(postboot)
+add_subdirectory(sysconfig)
add_subdirectory(tests)
### Installation
diff --git a/src/include/matahari/sysconfig.h b/src/include/matahari/sysconfig.h
new file mode 100644
index 0000000..dc277d1
--- /dev/null
+++ b/src/include/matahari/sysconfig.h
@@ -0,0 +1,98 @@
+/* sysconfig.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 Config API
+ * \ingroup coreapi
+ */
+
+#ifndef __MH_SYSCONFIG_H__
+#define __MH_SYSCONFIG_H__
+
+#include <stdint.h>
+#include <glib.h>
+/*! Supported FLAGS */
+#define MH_SYSCONFIG_FLAG_FORCE (1 << 0)
+
+/**
+ * Download and process URI for configuration
+ *
+ * \param[in] uri the url of configuration item
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ * \param[in] key configuration key for keeping track of existing
+ * configuration runs
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern int
+mh_sysconfig_run_uri(const char *uri, uint32_t flags, const char *scheme, const char *key);
+
+/**
+ * Process a text blob
+ *
+ * \param[in] string the text blob to process, accepts a range of data from XML to Puppet classes
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ * \param[in] key configuration key for keeping track of existing
+ * configuration runs
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern int
+mh_sysconfig_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key);
+
+/**
+ * Query against a configuration object on the system
+ *
+ * \param[in] query the query command used
+ * \param[in] flags flags used
+ * \param[in] scheme the type of configuration i.e. puppet
+ *
+ * \retval 0 for success
+ * \retval-1 for failure
+ */
+extern const char *
+mh_sysconfig_query(const char *query, uint32_t flags, const char *scheme);
+
+/**
+ * Set system as configured
+ *
+ * \param[in] key config item to define
+ *
+ * \return TRUE if applying key to config succeeds
+ */
+extern gboolean
+mh_sysconfig_set_configured(const char *key);
+
+/**
+ * Test if system has been configured
+ *
+ * \param[in] flags allow a force reconfiguration
+ * \param[in] key config item to test if used
+ *
+ * \return TRUE if system is configured
+ */
+extern gboolean
+mh_sysconfig_is_configured(const char *key);
+
+#endif // __MH_SYSCONFIG_H__
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index a8bdddf..601d8cb 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -1,6 +1,6 @@
# Library
-set(LIBS mcommon mhost mnetwork mservice mpostboot)
+set(LIBS mcommon mhost mnetwork mservice msysconfig)
include_directories(${pcre_INCLUDE_DIRS})
# See http://sourceware.org/autobook/autobook/autobook_91.html for
@@ -26,18 +26,18 @@ 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})
-add_library (mpostboot SHARED postboot.c)
-set_target_properties(mpostboot PROPERTIES SOVERSION 1.0.0)
-target_link_libraries(mpostboot ${pcre_LIBRARIES} mcommon ${glib_LIBRARIES})
+add_library (msysconfig SHARED sysconfig.c sysconfig_${VARIANT}.c)
+set_target_properties(msysconfig PROPERTIES SOVERSION 1.0.0)
+target_link_libraries(msysconfig ${pcre_LIBRARIES} mcommon ${glib_LIBRARIES})
if(WIN32)
foreach (lib ${LIBS})
- target_link_libraries(${lib} wsock32)
- install(TARGETS ${lib} DESTINATION sbin)
+ target_link_libraries(${lib} wsock32 dnsapi)
+ install(TARGETS ${lib} DESTINATION sbin)
endforeach (lib ${LIBS})
else(WIN32)
foreach (lib ${LIBS})
- install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX})
+ install(TARGETS ${lib} DESTINATION lib${LIB_SUFFIX} curl)
endforeach (lib ${LIBS})
endif(WIN32)
diff --git a/src/lib/sysconfig.c b/src/lib/sysconfig.c
new file mode 100644
index 0000000..6b2938d
--- /dev/null
+++ b/src/lib/sysconfig.c
@@ -0,0 +1,106 @@
+/* sysconfig.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
+
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "matahari/utilities.h"
+#include "sysconfig_private.h"
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+#ifdef WIN32
+static const char keys_dir[] = "c:\\";
+#else
+static const char keys_dir[] = "/var/lib/matahari/";
+#endif
+
+static gboolean
+set_key(const char *key)
+{
+ char key_file[PATH_MAX];
+ const char contents[] = "ok";
+
+ g_snprintf(key_file, sizeof(key_file), "%s%s", keys_dir, key);
+ if (!g_file_set_contents(key_file, contents, strlen(contents), NULL)) {
+ mh_err("Could not set file %s", key_file);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+get_key(const char *key)
+{
+ char key_file[PATH_MAX];
+ char *contents;
+ size_t length;
+
+ g_snprintf(key_file, sizeof(key_file), "%s%s", keys_dir, key);
+ if (g_file_test(key_file, G_FILE_TEST_EXISTS)) {
+ g_file_get_contents(key_file, &contents, &length, NULL);
+ if ((strcmp(contents, "ok")) == 0) {
+ free(contents);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+gboolean
+mh_sysconfig_set_configured(const char *key)
+{
+ if (!set_key(key)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean
+mh_sysconfig_is_configured(const char *key)
+{
+ if (!get_key(key)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int
+mh_sysconfig_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key) {
+ return sysconfig_os_run_uri(uri, flags, scheme, key);
+}
+
+int
+mh_sysconfig_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key) {
+ return sysconfig_os_run_string(string, flags, scheme, key);
+}
+
+const char *
+mh_sysconfig_query(const char *query, uint32_t flags, const char *scheme) {
+ return sysconfig_os_query(query, flags, scheme);
+}
diff --git a/src/lib/sysconfig_linux.c b/src/lib/sysconfig_linux.c
new file mode 100644
index 0000000..4b1b222
--- /dev/null
+++ b/src/lib/sysconfig_linux.c
@@ -0,0 +1,164 @@
+/* sysconfig_linux.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <glib.h>
+#include <curl/curl.h>
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "matahari/utilities.h"
+#include "sysconfig_private.h"
+
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+static int
+sysconfig_os_download(const char *uri, FILE *fp)
+{
+ CURL *curl;
+ CURLcode res;
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ curl = curl_easy_init();
+ if (curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, uri);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
+ res = curl_easy_perform(curl);
+
+ if (CURLE_OK != res) {
+ return -1;
+ }
+ curl_easy_cleanup(curl);
+ }
+ curl_global_cleanup();
+ return 0;
+}
+
+
+static int
+sysconfig_os_run_puppet(const char *uri, const char *data)
+{
+ gboolean ret;
+ GError *error = NULL;
+ gchar *cmd[3];
+ char *filename = NULL;
+ int fd;
+ FILE *fp;
+
+ if (uri != NULL) {
+ snprintf(filename, PATH_MAX, "%s", "puppet_conf_XXXXXX");
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ return -1;
+ }
+ fp = fdopen(fd, "w+b");
+ if (fp == NULL) {
+ close(fd);
+ return -1;
+ }
+ if ((sysconfig_os_download(uri, fp)) != 0) {
+ fclose(fp);
+ return -1;
+ }
+ fclose(fp);
+ } else if (data != NULL) {
+ snprintf(filename, PATH_MAX, "%s", "puppet_conf_blob");
+ g_file_set_contents(filename, data, strlen(data), NULL);
+ } else {
+ return -1;
+ }
+
+ cmd[0] = "puppet";
+ cmd[1] = filename;
+ cmd[2] = NULL;
+ mh_info("Running %s %s", cmd[0], cmd[1]);
+ ret = g_spawn_async(NULL, cmd, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (ret == FALSE) {
+ g_error_free(error);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+sysconfig_os_run_augeas(const char *query, const char *data)
+{
+ mh_warn("not implemented\n");
+ return 0;
+}
+
+static const char *
+sysconfig_os_query_augeas(const char *query)
+{
+ const char *data = NULL;
+ mh_warn("not implemented\n");
+ return data;
+}
+
+int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ int rc = 0;
+
+ if (mh_sysconfig_is_configured(key) == FALSE || (flags & MH_SYSCONFIG_FLAG_FORCE)) {
+ if (strcasecmp(scheme, "puppet") == 0) {
+ rc = sysconfig_os_run_puppet(uri, NULL);
+ } else {
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+int
+sysconfig_os_run_string(const char *data, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ int rc = 0;
+
+ if (mh_sysconfig_is_configured(key) == FALSE || (flags & MH_SYSCONFIG_FLAG_FORCE)) {
+ if (strcasecmp(scheme, "puppet") == 0) {
+ rc = sysconfig_os_run_puppet(NULL, data);
+ } else {
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme)
+{
+ const char *data = NULL;
+
+ if (strcasecmp(scheme, "augeas") == 0) {
+ data = sysconfig_os_query_augeas(query);
+ }
+
+ return data;
+}
diff --git a/src/lib/sysconfig_private.h b/src/lib/sysconfig_private.h
new file mode 100644
index 0000000..f521ad4
--- /dev/null
+++ b/src/lib/sysconfig_private.h
@@ -0,0 +1,33 @@
+/* sysconfig_private.h - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 __MH_SYSCONFIG_PRIVATE_H_
+#define __MH_SYSCONFIG_PRIVATE_H_
+
+extern int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key);
+
+extern int
+sysconfig_os_run_string(const char *string, uint32_t flags, const char *scheme,
+ const char *key);
+
+extern const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme);
+
+#endif /* __MH_SYSCONFIG_PRIVATE_H_ */
diff --git a/src/lib/sysconfig_windows.c b/src/lib/sysconfig_windows.c
new file mode 100644
index 0000000..2b272e4
--- /dev/null
+++ b/src/lib/sysconfig_windows.c
@@ -0,0 +1,74 @@
+/* sysconfig_windows.c - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 <windows.h>
+#include <glib.h>
+
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+#include "sysconfig_private.h"
+
+MH_TRACE_INIT_DATA(mh_sysconfig);
+
+static int
+sysconfig_os_run_regedit(char *registry_file)
+{
+ gchar *cmd[4];
+ gboolean ret;
+ GError *error = NULL;
+
+ cmd[0] = "REGEDIT";
+ cmd[1] = "/S";
+ cmd[2] = registry_file;
+ cmd[3] = NULL;
+
+ ret = g_spawn_async(NULL, cmd, NULL, G_SPAWN_SEARCH_PATH,
+ NULL, NULL, NULL, &error);
+ if (ret == FALSE) {
+ g_error_free(error);
+ return -1;
+ }
+ return 0;
+}
+
+int
+sysconfig_os_run_uri(const char *uri, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ return 0;
+}
+
+int
+sysconfig_os_run_string(const char *data, uint32_t flags, const char *scheme,
+ const char *key)
+{
+ char filename[PATH_MAX];
+ g_snprintf(filename, sizeof(filename), "%s\\%s.REG", g_getenv("TEMP"), key);
+ if (strcasecmp(scheme, "registry") == 0 ) {
+ g_file_set_contents(filename, data, strlen(data), NULL);
+ return sysconfig_os_run_regedit(filename);
+ }
+ return 0;
+}
+
+const char *
+sysconfig_os_query(const char *query, uint32_t flags, const char *scheme)
+{
+ const char *data = NULL;
+ return data;
+}
diff --git a/src/sysconfig/CMakeLists.txt b/src/sysconfig/CMakeLists.txt
new file mode 100644
index 0000000..1d9fba8
--- /dev/null
+++ b/src/sysconfig/CMakeLists.txt
@@ -0,0 +1,30 @@
+set(BASE "sysconfig")
+set(BASE_LIB "m${BASE}")
+set(QMF_AGENT "matahari-qmf-${BASE}d")
+set(QMF_CONSOLE "matahari-qmf-${BASE}-consoled")
+
+# 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})
+ add_executable(${QMF_CONSOLE} ${BASE}-console.cpp)
+
+ target_link_libraries(${QMF_AGENT} ${BASE_LIB} mcommon_qmf)
+ target_link_libraries(${QMF_CONSOLE} mcommon_qmf)
+
+ if(NOT WIN32)
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ # Override BASE for matahari-sysconfig-console
+ unset(BASE)
+ set(BASE "sysconfig-console")
+ configure_file(${CMAKE_SOURCE_DIR}/matahari.init.in ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE})
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/matahari-${BASE} DESTINATION ${initdir})
+ endif(NOT WIN32)
+
+ install(TARGETS ${QMF_AGENT} DESTINATION sbin)
+ install(TARGETS ${QMF_CONSOLE} DESTINATION sbin)
+endif(WITH-QMF)
diff --git a/src/sysconfig/schema.xml b/src/sysconfig/schema.xml
new file mode 100644
index 0000000..fa94bd5
--- /dev/null
+++ b/src/sysconfig/schema.xml
@@ -0,0 +1,39 @@
+<schema package="org.matahariproject">
+
+ <!-- Config API -->
+ <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="is_postboot_configured" type="uint32" access="RO" desc="Check if agent is configured." />
+
+ <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="uint32" />
+ </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="uint32" />
+ </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>
+
+ <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>
+ </class>
+</schema>
diff --git a/src/sysconfig/sysconfig-console.cpp b/src/sysconfig/sysconfig-console.cpp
new file mode 100644
index 0000000..ac40fb8
--- /dev/null
+++ b/src/sysconfig/sysconfig-console.cpp
@@ -0,0 +1,97 @@
+/* config-console.cpp - Copyright (c) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include <qpid/messaging/Connection.h>
+#include <qpid/messaging/Duration.h>
+#include <qmf/ConsoleSession.h>
+#include <qmf/ConsoleEvent.h>
+#include <qmf/Agent.h>
+#include <qmf/Data.h>
+#include <qmf/DataAddr.h>
+#include <qmf/Query.h>
+#include <qpid/types/Variant.h>
+
+#include "matahari/agent.h"
+
+#include <string>
+#include <iostream>
+#include <sstream>
+
+extern "C" {
+#include "matahari/logging.h"
+#include "matahari/sysconfig.h"
+}
+
+using namespace std;
+using namespace qmf;
+using qpid::types::Variant;
+using qpid::messaging::Duration;
+
+int main(int argc, char **argv)
+{
+ qpid::types::Variant::Map options;
+ qpid::types::Variant::Map callOptions;
+ string sessionOptions;
+ ConsoleEvent event;
+ Agent agent;
+
+ mh_log_init("sysconfig-console", LOG_TRACE, TRUE);
+
+ mh_add_option('U', required_argument, "uri", "URI of configuration", &options, NULL);
+
+ qpid::types::Variant::Map urlMap = mh_parse_options("sysconfig-console", argc, argv, options);
+
+ callOptions["uri"] = options["uri"];
+
+ mh_log_init("sysconfig-console", mh_log_level, mh_log_level > LOG_INFO);
+
+ qpid::messaging::Connection connection(urlMap["uri"], options);
+ connection.open();
+
+ ConsoleSession session(connection, sessionOptions);
+ // Only filter connecting agents under matahariproject.org vendor and Config product
+ session.setAgentFilter("[and, [eq, _vendor, [quote, 'matahariproject.org']], [eq, _product, [quote, 'Sysconfig']]]");
+ session.open();
+
+ while(session.getAgentCount() == 0) {
+ g_usleep(1000);
+ }
+
+ while (true) {
+ if(session.nextEvent(event)) {
+ switch(event.getType()) {
+ case CONSOLE_AGENT_ADD:
+ {
+ agent = event.getAgent();
+ DataAddr agent_event_addr("config", agent.getName(), 0);
+ ConsoleEvent result(agent.callMethod("run_uri",
+ callOptions,
+ agent_event_addr));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return 0;
+}
diff --git a/src/sysconfig/sysconfig-qmf.cpp b/src/sysconfig/sysconfig-qmf.cpp
new file mode 100644
index 0000000..2e405f1
--- /dev/null
+++ b/src/sysconfig/sysconfig-qmf.cpp
@@ -0,0 +1,123 @@
+/* sysconfig-qmf.cpp - Copyright (C) 2011 Red Hat, Inc.
+ * Written by Adam Stokes <astokes(a)fedoraproject.org>
+ *
+ * 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 Sysconfig QMF Agent
+ */
+
+#ifndef WIN32
+#include "config.h"
+#endif
+
+#include <qpid/agent/ManagementAgent.h>
+#include "qmf/org/matahariproject/QmfPackage.h"
+#include "matahari/agent.h"
+
+extern "C" {
+#include "matahari/logging.h"
+#include "matahari/host.h"
+#include "matahari/sysconfig.h"
+};
+
+class ConfigAgent : public MatahariAgent
+{
+private:
+ qmf::org::matahariproject::PackageDefinition _package;
+ qmf::Data _instance;
+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)
+{
+ ConfigAgent agent;
+ int rc = agent.init(argc, argv, "Sysconfig");
+ if (rc == 0) {
+ agent.run();
+ }
+ return rc;
+}
+
+int
+ConfigAgent::setup(qmf::AgentSession session)
+{
+ _package.configure(session);
+ _instance = qmf::Data(_package.data_Sysconfig);
+
+ _instance.setProperty("hostname", mh_hostname());
+ _instance.setProperty("uuid", mh_uuid());
+ _instance.setProperty("is_postboot_configured", 0);
+
+ session.addData(_instance, "sysconfig");
+ return 0;
+}
+
+gboolean
+ConfigAgent::invoke(qmf::AgentSession session, qmf::AgentEvent event, gpointer user_data)
+{
+ int rc = 0;
+
+ const std::string& methodName(event.getMethodName());
+ if (event.getType() != qmf::AGENT_METHOD) {
+ return TRUE;
+ }
+
+ qpid::types::Variant::Map& args = event.getArguments();
+
+ if (methodName == "run_uri") {
+ rc = mh_sysconfig_run_uri(args["uri"].asString().c_str(),
+ args["flags"].asUint32(),
+ args["scheme"].asString().c_str(),
+ args["key"].asString().c_str());
+ if (rc == 0) {
+ mh_sysconfig_set_configured(args["key"].asString().c_str());
+ }
+ event.addReturnArgument("status", rc);
+ } else if (methodName == "run_string") {
+ rc = mh_sysconfig_run_string(args["data"].asString().c_str(),
+ args["flags"].asUint32(),
+ args["scheme"].asString().c_str(),
+ args["key"].asString().c_str());
+ if (rc == 0) {
+ mh_sysconfig_set_configured(args["key"].asString().c_str());
+ }
+ event.addReturnArgument("status", rc);
+ } else if (methodName == "query") {
+ const char *data = NULL;
+ data = mh_sysconfig_query(args["query"].asString().c_str(),
+ args["flags"].asUint32(),
+ args["scheme"].asString().c_str());
+ event.addReturnArgument("query", data);
+ } else if (methodName == "is_configured") {
+ rc = mh_sysconfig_is_configured(args["key"].asString().c_str());
+ _instance.setProperty("is_postboot_configured", rc);
+ event.addReturnArgument("status", rc);
+ } else {
+ session.raiseException(event, MH_NOT_IMPLEMENTED);
+ goto bail;
+ }
+
+ session.methodSuccess(event);
+
+bail:
+ return TRUE;
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 6db157c..8fe81f2 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -5,13 +5,13 @@ if(CXXTEST_FOUND)
ENABLE_TESTING()
CXXTEST_ADD_TEST(mh_api_network_unittest network_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_network.h)
CXXTEST_ADD_TEST(mh_api_host_unittest host_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_host.h)
- CXXTEST_ADD_TEST(mh_api_postboot_unittest postboot_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_postboot.h)
+ CXXTEST_ADD_TEST(mh_api_sysconfig_unittest sysconfig_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_api_sysconfig.h)
CXXTEST_ADD_TEST(mh_hsa_unittest hsa_unittest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mh_hsa_${VARIANT}.h)
add_library(mh_tester SHARED test_utilities.c)
- target_link_libraries(mh_tester ${pcre_LIBRARIES} mcommon mnetwork mhost mpostboot)
+ target_link_libraries(mh_tester ${pcre_LIBRARIES} mcommon mnetwork mhost msysconfig)
target_link_libraries(mh_api_network_unittest mh_tester)
target_link_libraries(mh_api_host_unittest mh_tester)
- target_link_libraries(mh_api_postboot_unittest mh_tester)
+ target_link_libraries(mh_api_sysconfig_unittest mh_tester)
target_link_libraries(mh_hsa_unittest mh_tester)
endif(CXXTEST_FOUND)
diff --git a/src/tests/mh_api_sysconfig.h b/src/tests/mh_api_sysconfig.h
new file mode 100644
index 0000000..0f0734e
--- /dev/null
+++ b/src/tests/mh_api_sysconfig.h
@@ -0,0 +1,37 @@
+#ifndef __MH_API_NETWORK_UNITTEST_H
+#define __MH_API_NETWORK_UNITTEST_H
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <utility>
+#include <vector>
+#include <cstdlib>
+#include <cstdio>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <cxxtest/TestSuite.h>
+
+extern "C" {
+#include "matahari/sysconfig.h"
+#include <glib.h>
+#include "mh_test_utilities.h"
+};
+
+using namespace std;
+
+class MhApiSysconfigSuite : public CxxTest::TestSuite
+{
+ public:
+
+ void testIsConfigured(void)
+ {
+ const char *uri = "http://matahariproject.org/atom.xml"; // Test if download succeeds
+ const char flags = 0;
+ const char key[] = "org.matahariproject.firstboot"; // Unimportant key defined
+ TS_ASSERT((mh_sysconfig_set_configured(key)) == TRUE);
+ TS_ASSERT((mh_sysconfig_is_configured(key)) == TRUE);
+ TS_ASSERT((mh_sysconfig_run_uri(uri, flags, "puppet", key)) != -1);
+ }
+};
+
+#endif
--
1.7.6
12 years, 9 months
[PATCH] - Update tests to work with uuid changes to host
by Adam Stokes
Signed-off-by: Adam Stokes <astokes(a)fedoraproject.org>
---
src/tests/mh_api_host.h | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/tests/mh_api_host.h b/src/tests/mh_api_host.h
index 0911b30..4786255 100644
--- a/src/tests/mh_api_host.h
+++ b/src/tests/mh_api_host.h
@@ -64,9 +64,10 @@ class MhApiHostSuite : public CxxTest::TestSuite
void testUuid(void)
{
- infomsg << "Verify " << mh_host_get_uuid() << " exists";
+ const char *lifetime = NULL;
+ infomsg << "Verify " << mh_host_get_uuid(lifetime) << " exists";
TS_TRACE(infomsg.str());
- TS_ASSERT((mh_test_is_match("^[0-9a-zA-Z]+$", mh_host_get_uuid())) >= 0);
+ TS_ASSERT((mh_test_is_match("^[0-9a-zA-Z]+$", mh_host_get_uuid(lifetime))) >= 0);
infomsg.str("");
}
--
1.7.6
12 years, 9 months
[PATCH] - Connection fallback v3
by Adam Stokes
- Parses everything URI related into a map for easy retrieval
during reconnect phase
- Fallback methods for invalid hostname, localhost, to fallback on
DNS srv records and localhost/specified domain indefinately.
Signed-off-by: Adam Stokes <astokes(a)fedoraproject.org>
---
src/include/matahari/agent.h | 6 +-
src/lib/mh_agent.cpp | 111 +++++++++++++++++++++-------------
src/service/service-qmf-console.cpp | 5 +-
3 files changed, 74 insertions(+), 48 deletions(-)
diff --git a/src/include/matahari/agent.h b/src/include/matahari/agent.h
index a65fde5..3f9ed62 100644
--- a/src/include/matahari/agent.h
+++ b/src/include/matahari/agent.h
@@ -1,7 +1,6 @@
/* mh_agent.cpp - Copyright (C) 2010 Red Hat, Inc.
* Written by 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
@@ -47,6 +46,9 @@ int required_argument = 1;
#define MH_NOT_IMPLEMENTED "Not implemented"
+#ifndef NS_MAXDNAME
+# define NS_MAXDNAME 1025
+#endif
using namespace qpid::management;
using namespace std;
@@ -67,7 +69,7 @@ extern int mh_add_option(
int code, int has_arg, const char *name, const char *description,
void *userdata, int(*callback)(int code, const char *name, const char *arg, void *userdata));
-extern string mh_parse_options(
+extern qpid::types::Variant::Map mh_parse_options(
const char *proc_name, int argc, char **argv, qpid::types::Variant::Map &options);
extern mainloop_qmf_t *mainloop_add_qmf(int priority, qmf::AgentSession session,
diff --git a/src/lib/mh_agent.cpp b/src/lib/mh_agent.cpp
index e233244..0748610 100644
--- a/src/lib/mh_agent.cpp
+++ b/src/lib/mh_agent.cpp
@@ -42,8 +42,13 @@ int use_stderr = 0;
#include "matahari/agent.h"
extern "C" {
+#include <sys/types.h>
#include "matahari/logging.h"
#include "matahari/dnssrv.h"
+#ifndef WIN32
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
}
using namespace qpid::management;
@@ -192,22 +197,18 @@ int print_help(int code, const char *name, const char *arg, void *userdata)
return 0;
}
-string
+qpid::types::Variant::Map
mh_parse_options(const char *proc_name, int argc, char **argv, qpid::types::Variant::Map &options)
{
std::stringstream url;
+ qpid::types::Variant::Map urlMap;
- int arg;
- int serverport = MATAHARI_PORT;
- char *servername = NULL;
-
- const char *protocol = NULL;
const char *ssl_cert_db = NULL;
const char *ssl_cert_name = NULL;
const char *ssl_cert_password_file = NULL;
int lpc = 0;
- options["reconnect"] = true;
+ options["reconnect"] = false;
/* Force local-only handling */
mh_add_option('b', required_argument, "broker", NULL, NULL, NULL);
@@ -229,15 +230,14 @@ mh_parse_options(const char *proc_name, int argc, char **argv, qpid::types::Vari
if (RegistryRead(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\services\\Matahari",
L"broker", &value) == 0) {
- free(servername);
- servername = value;
+ urlMap["servername"] = value;
value = NULL;
}
if (RegistryRead(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\services\\Matahari",
L"port", &value) == 0) {
- serverport = atoi(value);
+ urlMap["serverport"] = atoi(value);
free(value);
value = NULL;
}
@@ -264,6 +264,8 @@ mh_parse_options(const char *proc_name, int argc, char **argv, qpid::types::Vari
int opt_string_len = 0;
char opt_string[2 * DIMOF(matahari_options)];
struct option *long_opts = (struct option *)calloc(1, sizeof(struct option));
+ struct addrinfo hints, *res;
+ int rc, arg;
/* Force more local-only processing */
mh_add_option('h', no_argument, "help", NULL, NULL, NULL);
@@ -304,10 +306,17 @@ mh_parse_options(const char *proc_name, int argc, char **argv, qpid::types::Vari
mh_enable_stderr(1);
break;
case 'p':
- serverport = atoi(optarg);
+ urlMap["serverport"] = optarg;
break;
case 'b':
- servername = strdup(optarg);
+ urlMap["servername"] = optarg;
+#ifndef WIN32
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ if ((rc = getaddrinfo(urlMap["servername"].asString().c_str(), NULL, &hints, &res)) != 0) {
+ urlMap["servername"] = string("localhost");
+ }
+#endif
break;
case 'N':
ssl_cert_name = optarg;
@@ -359,34 +368,21 @@ mh_parse_options(const char *proc_name, int argc, char **argv, qpid::types::Vari
#endif
if (ssl_cert_name && ssl_cert_db && ssl_cert_password_file) {
- protocol = "ssl";
+ urlMap["protocol"] = "ssl";
} else {
- protocol = "tcp";
+ urlMap["protocol"] = "tcp";
}
- /*
- * Based on servername do a SRV lookup for best possible
- * server providing this service.
- */
- if (servername) {
-#ifdef HAVE_RESOLV_A
- int ret;
- char query[NS_MAXDNAME];
- char target[NS_MAXDNAME];
- g_snprintf(query, sizeof(query), "_matahari._tcp.%s", servername);
- ret = mh_srv_lookup(query, target, sizeof(target));
- if (ret == 0) {
- servername = strdup(target);
- }
-#endif
- } else {
- servername = strdup(MATAHARI_BROKER);
+ if(urlMap["servername"].asString().empty()) {
+ urlMap["servername"] = string("localhost");
}
+ if(urlMap["serverport"].asString().empty()) {
+ urlMap["serverport"] = string("49000");
+ }
+ url << "amqp:" << urlMap["protocol"] << ":" << urlMap["servername"] << ":" << urlMap["serverport"] ;
+ urlMap["uri"] = url.str();
- url << "amqp:" << protocol << ":" << servername << ":" << serverport ;
-
- free(servername);
- return url.str();
+ return urlMap;
}
int
@@ -445,9 +441,7 @@ MatahariAgent::init(int argc, char **argv, const char* proc_name)
mh_log_init(proc_name, LOG_INFO, TRUE);
mh_add_option('d', no_argument, "daemon", "run as a daemon", NULL, should_daemonize);
- string url = mh_parse_options(proc_name, argc, argv, options);
-
- cout << options << endl;
+ qpid::types::Variant::Map urlMap = mh_parse_options(proc_name, argc, argv, options);
/* Re-initialize logging now that we've completed option processing */
@@ -456,10 +450,41 @@ MatahariAgent::init(int argc, char **argv, const char* proc_name)
// Set up the cleanup handler for sigint
signal(SIGINT, shutdown);
- mh_info("Connecting %s to Qpid broker at %s", proc_name, url.c_str());
-
- _impl->_amqp_connection = qpid::messaging::Connection(url, options);
- _impl->_amqp_connection.open();
+ mh_info("Connecting %s to Qpid broker at %s", proc_name, urlMap["uri"].asString().c_str());
+
+ _impl->_amqp_connection = qpid::messaging::Connection(urlMap["uri"], options);
+ try {
+ _impl->_amqp_connection.open();
+ } catch (const std::exception& err) {
+ while (!_impl->_amqp_connection.isOpen()) {
+ mh_info("Trying DNS SRV");
+ std::stringstream url;
+ url << "amqp:tcp:";
+ int ret;
+ char query[NS_MAXDNAME];
+ char target[NS_MAXDNAME];
+ g_snprintf(query, sizeof(query), "_matahari._tcp.%s", urlMap["servername"].asString().c_str());
+ ret = mh_srv_lookup(query, target, sizeof(target));
+ if (ret == 0) {
+ url << target << ":" << urlMap["serverport"];
+ urlMap["uri"] = url.str();
+ }
+ _impl->_amqp_connection = qpid::messaging::Connection(urlMap["uri"], options);
+ try {
+ _impl->_amqp_connection.open();
+ } catch (const std::exception& err2) {
+ mh_info("Trying qpid broker %s again", urlMap["servername"].asString().c_str());
+ url << urlMap["servername"] << ":" << urlMap["serverport"];
+ urlMap["uri"] = url.str();
+ _impl->_amqp_connection = qpid::messaging::Connection(urlMap["uri"], options);
+ try {
+ _impl->_amqp_connection.open();
+ } catch (const std::exception& err3) {
+ g_usleep(G_USEC_PER_SEC);
+ }
+ }
+ }
+ }
_impl->_agent_session = qmf::AgentSession(_impl->_amqp_connection);
_impl->_agent_session.setVendor("matahariproject.org");
@@ -472,7 +497,7 @@ MatahariAgent::init(int argc, char **argv, const char* proc_name)
/* Do any setup required by our agent */
if (this->setup(_impl->_agent_session) < 0) {
mh_err("Failed to set up broker connection to %s for %s\n",
- url.c_str(), proc_name);
+ urlMap["servername"].asString().c_str(), proc_name);
res = -1;
goto return_cleanup;
}
diff --git a/src/service/service-qmf-console.cpp b/src/service/service-qmf-console.cpp
index f89bd1c..3f66a12 100644
--- a/src/service/service-qmf-console.cpp
+++ b/src/service/service-qmf-console.cpp
@@ -96,12 +96,11 @@ int main(int argc, char** argv)
mh_add_option('o', required_argument, "option", "Option to pass to the resource script (Resources API only)", NULL, NULL);
- string url = mh_parse_options("service-console", argc, argv, options);
+ qpid::types::Variant::Map url = mh_parse_options("service-console", argc, argv, options);
/* Re-initialize logging now that we've completed option processing */
mh_log_init("service-console", mh_log_level, mh_log_level > LOG_INFO);
-
- qpid::messaging::Connection connection(url, options);
+ qpid::messaging::Connection connection(url["uri"], options);
connection.open();
ConsoleSession session(connection, sessionOptions);
--
1.7.6
12 years, 9 months
Third-party matahari agents
by Zane Bitter
Since libvirt-qpid (or, rather, libvirt-qmf) seems to be the first
matahari agent to be created outside of the matahari package, I have
collected a few observations gathered from writing it. One big caveat
here is that this applies only to the QMF side of things; I have spent
no time with DBus to date.
1) Missing headers
I've already added a patch to export mainloop.h. I think we also need to
export logging.h. Also note that these headers currently don't have the
mh_ prefix. Maybe that's not really required because they are in the
matahari/ directory already, but it's not consistent.
(Incidentally, this change needs to be in Fedora before we can add the
libvirt-qmf package since the latter won't build without it.)
2) Oddly-named libraries
On the subject of prefixes, the prefix used for the matahari libraries,
namely "m", is... not the *most* effective thing for avoiding name
collisions that I could think of, nor the easiest thing to search for.
3) No stable ABI
In the past matahari has had to be regularly rebuilt due to the lack of
a stable ABI in qpid-cpp. This has now been fixed in the QMFv2 API, but
the lack of the same sort of provisions in matahari means that we will
potentially be creating the same sorts of issues for downstream projects.
4) Simplistic object model
All of the internal agents publish only a single object. It's even
hard-wired into the MatahariAgent class even though it is not required
there (I have a patch to change this). Y'all will have noticed that I
had to write a bunch of helper classes to simplify handling of the
multiple objects that libvirt-qmf manages. Even now, it's still doing a
horrible linear lookup to do method dispatch. I'd like to replace this
with something (in matahari) that registers the objects and does method
dispatch from a hash table. (Oddly, QMFv1 provided helpers for method
dispatch, but QMFv2 does not seem to... if anybody has better
information I would be interested to hear it.)
5) Limited support for error handling
Returning an error from a function in such a way as to return anything
other than a generic error code and a string is surprisingly complicated
in QMFv2 (again, if anybody knows any easier way I'd like to hear it).
There is an MH_NOT_IMPLEMENTED string defined, but that is the only one.
And using it still results in the error code STATUS_EXCEPTION, even
though there is an error code in QMF(v1) for STATUS_NOT_IMPLEMENTED.
This seems like an area where matahari could add value.
Since widespread adoption of matahari depends in large part on other
folks wanting to write matahari agents to expose their APIs, I think it
would be valuable to address some of these areas to make it easier for
them to do so. Preferably before any other agents get out in the wild,
so that we are not shifting the goalposts for other projects. Comments?
regards,
Zane.
12 years, 9 months
Sysconfig Agent RFC
by Adam Stokes
Matahari Sysconfig agent
synopsis:
- Provide a catch all proxy to allow third party
applications remote configuration capabilities.
design api:
is_configured - A Matahari property provided from the agent to
determine whether a system has been configured or not.
mh_configure ( URI, TYPE) :
- The URI should be able to translate properly given any number of
protocols:
- HTTP|HTTPS|FILE|PUPPET|KS
- The protocols will be defined by TYPE:
- KICKSTART, PUPPET, HTTP, FTP
- The agent message content should be able to retrieve configs in
several ways
- Directly from a QPID message.
The message should contain some metadata describing the
config as well as the configuration itself.
Some things to note, the configuration must be
transferred unaltered in case third party applications
require correct syntax (INI, YAML)
- Through HTTP,FTP,SCP, etc.
With the use of a library like libcurl we can support
several protocols through the use of a URL syntax, see
curl.haxx.se for a brief description.
- Once configuration is obtained the ability to initiate the
configuration or verify a third party will initiate configuration is
needed.
12 years, 9 months