rrd based system stats
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

255 lines
6.3 KiB

  1. /***************************************************************************
  2. * Copyright (C) 06/2006 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #if (WITH_RRD)
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <sys/stat.h>
  26. #include <errno.h>
  27. #include <rrd.h>
  28. #include "configfile.h"
  29. #include "helper.h"
  30. #include "linebuffer.h"
  31. #include "list.h"
  32. #include "logging.h"
  33. #include "plugins.h"
  34. #define DEFAULT_STEP 10
  35. #define ARGCMAX 64
  36. #define ARGVSIZE 1024
  37. #define BUFSIZE 1024
  38. static const char *rrd_dir;
  39. int sammler_rrd_init(void)
  40. {
  41. rrd_dir = config_get_string("global", "rrd_dir", ".");
  42. return 0;
  43. }
  44. static int append_rra_config(const char *parameter, void *privdata)
  45. {
  46. struct lbuf *buffer = (struct lbuf *)privdata;
  47. lbuf_printf(buffer, "%s ", parameter);
  48. return 0;
  49. }
  50. static int do_rrd(int (*rrd_func)(int, char **), struct lbuf *buffer)
  51. {
  52. size_t len;
  53. char *cmd = lbuf_getdata(buffer, &len);
  54. if (len < ARGVSIZE -1)
  55. cmd[len] = '\0';
  56. char *argv[ARGCMAX];
  57. int argc = strsplit(cmd, " \t\n", argv, ARGCMAX -1);
  58. argv[argc] = NULL;
  59. optind = 0;
  60. rrd_clear_error();
  61. int retval = rrd_func(argc, argv);
  62. if (retval == -1) {
  63. errno = 0;
  64. log_print(LOG_ERROR, "rrd_func failed: %s: %s", argv[1], rrd_get_error());
  65. }
  66. return retval;
  67. }
  68. static int rrd_create_file(const char *filename, const char *pluginname, int ds_id)
  69. {
  70. struct sammler_plugin *plugin = plugin_lookup(pluginname);
  71. if (plugin == NULL) {
  72. log_print(LOG_ERROR, "rrd_create_file: plugin not found (%s)", pluginname);
  73. return -1;
  74. }
  75. const char *ds_def = plugin->get_ds(ds_id);
  76. if (ds_def == NULL) {
  77. log_print(LOG_ERROR, "No vaild DS found (%s:%d)", plugin->name, ds_id);
  78. return -1;
  79. }
  80. struct lbuf *buffer = lbuf_create(ARGVSIZE);
  81. if (buffer == NULL) {
  82. log_print(LOG_ERROR, "rrd_create_file: out of memory");
  83. return -1;
  84. }
  85. int ret = lbuf_printf(buffer, "create %s -s %d %s ", filename, plugin->interval, ds_def);
  86. if (ret == -1) {
  87. log_print(LOG_ERROR, "rrd_create_file: arguments too long");
  88. lbuf_free(buffer);
  89. return -1;
  90. }
  91. ret = config_get_strings("global", "rra", append_rra_config, buffer);
  92. if (ret <= 0) {
  93. lbuf_free(buffer);
  94. return -1;
  95. }
  96. ret = do_rrd(&rrd_create, buffer);
  97. lbuf_free(buffer);
  98. return ret;
  99. }
  100. static int rrd_update_file(const char *filename, const char *values)
  101. {
  102. struct lbuf *buffer = lbuf_create(ARGVSIZE);
  103. if (buffer == NULL) {
  104. log_print(LOG_ERROR, "append_ds_config: out of memory");
  105. return -1;
  106. }
  107. int ret = lbuf_printf(buffer, "update %s N:%s", filename, values);
  108. if (ret == -1) {
  109. log_print(LOG_ERROR, "rrd_update_file: arguments too long");
  110. lbuf_free(buffer);
  111. return -1;
  112. }
  113. ret = do_rrd(&rrd_update, buffer);
  114. lbuf_free(buffer);
  115. return ret;
  116. }
  117. static int check_create_dir(const char *dir)
  118. {
  119. struct stat statbuf;
  120. if (stat(dir, &statbuf) == -1) {
  121. if (errno == ENOENT) {
  122. errno = 0;
  123. if (mkdir(dir, 0755) == -1) {
  124. log_print(LOG_ERROR, "check_create_dir: mkdir(%s)", dir);
  125. return -1;
  126. }
  127. } else {
  128. log_print(LOG_ERROR, "check_create_dir: stat(%s)", dir);
  129. return -1;
  130. }
  131. } else if (!S_ISDIR (statbuf.st_mode)) {
  132. log_print(LOG_ERROR, "check_create_dir: stat(%s): Not a directory!", dir);
  133. return -1;
  134. }
  135. return 0;
  136. }
  137. static int create_parent_dirs(char *filename)
  138. {
  139. char *nextslash = filename;
  140. char *lastslash = strrchr(filename, '/');
  141. if (lastslash == NULL) {
  142. log_print(LOG_ERROR, "create_parent_dirs: invalid file name");
  143. return -1;
  144. }
  145. *lastslash = '\0';
  146. while (1) {
  147. if (strchr(nextslash, '/') == NULL) {
  148. if (*lastslash == '\0')
  149. *lastslash = '/';
  150. else
  151. break;
  152. }
  153. nextslash = strchr(nextslash, '/');
  154. *nextslash = '\0';
  155. if (filename != nextslash) {
  156. if (check_create_dir(filename) == -1) {
  157. *nextslash = '/';
  158. *lastslash = '/';
  159. return -1;
  160. }
  161. }
  162. *nextslash++ = '/';
  163. }
  164. return 0;
  165. }
  166. int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
  167. {
  168. char *fullfile = malloc(BUFSIZE);
  169. if (fullfile == NULL) {
  170. log_print(LOG_ERROR, "rrd_submit: out of memory");
  171. return -1;
  172. }
  173. int len = snprintf(fullfile, BUFSIZE, "%s/%s/%s", rrd_dir, hostname, filename);
  174. if (len < 0 || len >= BUFSIZE) {
  175. log_print(LOG_ERROR, "rrd_submit: arguments too long");
  176. free(fullfile);
  177. return -1;
  178. }
  179. struct stat statbuf;
  180. if (stat(fullfile, &statbuf) == -1) {
  181. if (errno == ENOENT) {
  182. errno = 0;
  183. if (create_parent_dirs(fullfile) == -1) {
  184. free(fullfile);
  185. return -1;
  186. }
  187. if (rrd_create_file(fullfile, pluginname, ds_id) == -1) {
  188. free(fullfile);
  189. return -1;
  190. }
  191. } else {
  192. log_print(LOG_ERROR, "rrd_submit: stat(%s):", fullfile);
  193. free(fullfile);
  194. return -1;
  195. }
  196. } else if (!S_ISREG (statbuf.st_mode)) {
  197. log_print(LOG_ERROR, "rrd_submit: stat(%s): Not a regular file!", fullfile);
  198. free(fullfile);
  199. return -1;
  200. }
  201. rrd_update_file(fullfile, data);
  202. free(fullfile);
  203. return 0;
  204. }
  205. #else /* (WITH_RRD) */
  206. int sammler_rrd_init(void)
  207. {
  208. return 0;
  209. }
  210. int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
  211. {
  212. return 0;
  213. }
  214. #endif /* (WITH_RRD) */