00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <netcomm/fawkes/client.h>
00024 #include <config/netconf.h>
00025 #include <utils/system/argparser.h>
00026 #include <utils/system/signal.h>
00027
00028 #include <iostream>
00029 #include <cstring>
00030 #include <cstdlib>
00031 #include <cstdio>
00032
00033 using namespace fawkes;
00034
00035
00036
00037 class ConfigChangeWatcherTool : public ConfigurationChangeHandler, public SignalHandler
00038 {
00039 public:
00040
00041
00042
00043
00044
00045 ConfigChangeWatcherTool(Configuration *config, FawkesNetworkClient *c)
00046 {
00047 this->c = c;
00048 this->config = config;
00049 quit = false;
00050 config->add_change_handler(this);
00051 }
00052
00053 virtual void handle_signal(int signal)
00054 {
00055 config->rem_change_handler(this);
00056 quit = true;
00057 }
00058
00059 virtual void config_tag_changed(const char *new_tag)
00060 {
00061 printf("--> New tag loaded: %s\n", new_tag);
00062 }
00063
00064 virtual void config_value_changed(const char *path, bool is_default, int value)
00065 {
00066 printf("%s %-55s| %-8s| %-14i\n", is_default ? "*" : " ", path, "int", value);
00067 }
00068
00069 virtual void config_value_changed(const char *path, bool is_default, unsigned int value)
00070 {
00071 printf("%s %-55s| %-8s| %-14u\n", is_default ? "*" : " ", path, "uint", value);
00072 }
00073
00074 virtual void config_value_changed(const char *path, bool is_default, float value)
00075 {
00076 printf("%s %-55s| %-8s| %-14f\n", is_default ? "*" : " ", path, "float", value);
00077 }
00078
00079 virtual void config_value_changed(const char *path, bool is_default, bool value)
00080 {
00081 printf("%s %-55s| %-8s| %-14s\n", is_default ? "*" : " ", path, "bool", (value ? "true" : "false"));
00082 }
00083
00084 virtual void config_value_changed(const char *path, bool is_default, const char *value)
00085 {
00086 printf("%s %-55s| %-8s| %-14s\n", is_default ? "*" : " ", path, "string", value);
00087 }
00088
00089 virtual void config_comment_changed(const char *path, bool is_default, const char *comment)
00090 {
00091 printf("%s %s: %s\n", is_default ? "C" : "c", path, comment);
00092 }
00093
00094 virtual void config_value_erased(const char *path, bool is_default)
00095 {
00096 printf("%s %-55s| %-8s| %-14s\n", is_default ? "*" : " ", path, "", "ERASED");
00097 }
00098
00099
00100
00101
00102
00103 void
00104 run()
00105 {
00106 while ( ! quit ) {
00107 c->wait(FAWKES_CID_CONFIGMANAGER);
00108 }
00109 }
00110
00111 private:
00112 FawkesNetworkClient *c;
00113 Configuration *config;
00114 bool quit;
00115
00116 };
00117
00118
00119
00120 void
00121 print_header()
00122 {
00123 printf("D %-55s| %-8s| %-14s\n", "Path", "Type", "Value");
00124 printf("--------------------------------------------------------------------------------------\n");
00125 }
00126
00127
00128
00129
00130
00131 void
00132 print_line(Configuration::ValueIterator *i, bool show_comment = false)
00133 {
00134 if ( i->is_float() ) {
00135 printf("%s %-55s| %-8s| %-14f\n", (i->is_default() ? "*" : " "), i->path(), i->type(), i->get_float());
00136 } else if ( i->is_uint() ) {
00137 printf("%s %-55s| %-8s| %-14u\n", (i->is_default() ? "*" : " "), i->path(), "uint", i->get_uint());
00138 } else if ( i->is_int() ) {
00139 printf("%s %-55s| %-8s| %-14i\n", (i->is_default() ? "*" : " "), i->path(), i->type(), i->get_int());
00140 } else if ( i->is_bool() ) {
00141 printf("%s %-55s| %-8s| %-14s\n", (i->is_default() ? "*" : " "), i->path(), i->type(), (i->get_bool() ? "true" : "false"));
00142 } else if ( i->is_string() ) {
00143 printf("%s %-55s| %-8s| %-14s\n", (i->is_default() ? "*" : " "), i->path(), i->type(), i->get_string().c_str());
00144 }
00145
00146 if (show_comment) {
00147 try {
00148 std::string comment = i->get_comment();
00149 if (comment != "") {
00150 printf("C %-55s: %s\n", i->path(), comment.c_str());
00151 }
00152 } catch (Exception &e) {
00153
00154 }
00155 }
00156 }
00157
00158
00159 void
00160 print_usage(const char *program_name)
00161 {
00162 std::cout << "Usage: " << program_name << " [options] <cmd>" << std::endl
00163 << "where cmd is one of the following:" << std::endl << std::endl
00164 << " list" << std::endl
00165 << " List all configuration items" << std::endl << std::endl
00166 << " watch" << std::endl
00167 << " Watch configuration changes" << std::endl << std::endl
00168 << " get <path>" << std::endl
00169 << " Get value for the given path" << std::endl << std::endl
00170 << " set <path> <value> [type]" << std::endl
00171 << " Set value for the given path to the given type and value" << std::endl
00172 << " where type is one of float/uint/int/bool/string. The type" << std::endl
00173 << " is only necessary if you are creating a new value" << std::endl << std::endl
00174 << " set_default <path> <value> [type]" << std::endl
00175 << " Set default value for the given path to the given type and value" << std::endl
00176 << " where type is one of float/uint/int/bool/string. The type" << std::endl
00177 << " is only necessary if you are creating a new value" << std::endl << std::endl
00178 << " set_comment <path> <comment>" << std::endl
00179 << " Set comment for the given path to the given value. The value at" << std::endl
00180 << " the given path must already exist in the host-specific configuration." << std::endl << std::endl
00181 << " set_default_comment <path> <comment>" << std::endl
00182 << " Set default comment for the given path to the given value. The value at" << std::endl
00183 << " the given path must already exist in the default configuration." << std::endl << std::endl
00184 << " erase <path>" << std::endl
00185 << " Erase value for given path from config" << std::endl
00186 << " erase_default <path>" << std::endl
00187 << " Erase default value for given path from config" << std::endl << std::endl
00188 << "and options is none, one or more of the following:" << std::endl << std::endl
00189 << " -c Show comments (only available with list and watch cmd)" << std::endl
00190 << " -a Show all values, even double if default and host-specific " << std::endl
00191 << " values exist (only available with list)" << std::endl
00192 << std::endl;
00193 }
00194
00195
00196
00197
00198
00199 int
00200 main(int argc, char **argv)
00201 {
00202 ArgumentParser argp(argc, argv, "+hca");
00203
00204 if ( argp.has_arg("h") ) {
00205 print_usage(argv[0]);
00206 exit(0);
00207 }
00208
00209 FawkesNetworkClient *c = new FawkesNetworkClient("localhost", 1910);
00210 c->connect();
00211
00212 NetworkConfiguration *netconf = new NetworkConfiguration(c);
00213
00214 const std::vector< const char* > & args = argp.items();
00215
00216 if ( args.size() == 0) {
00217
00218 printf("Not enough args\n\n");
00219 print_usage(argv[0]);
00220 } else if (strcmp("get", args[0]) == 0) {
00221 if (args.size() == 2) {
00222 printf("Requesting value %s\n", args[1]);
00223 Configuration::ValueIterator *i = netconf->get_value(args[1]);
00224 if ( i->next() ) {
00225 print_header();
00226 print_line(i);
00227 } else {
00228 printf("No such value found!\n");
00229 }
00230 delete i;
00231 } else {
00232
00233 printf("You must supply path argument\n");
00234 }
00235 } else if ((strcmp("set", args[0]) == 0) || (strcmp("set_default", args[0]) == 0)) {
00236 bool set_def = (strcmp("set_default", args[0]) == 0);
00237 if (args.size() >= 3) {
00238
00239 printf("Requesting old value for %s\n", args[1]);
00240 Configuration::ValueIterator *i = netconf->get_value(args[1]);
00241 print_header();
00242 printf("OLD:\n");
00243 if ( i->next() ) {
00244 print_line(i);
00245 } else {
00246 printf("Value does not currently exist in configuration.\n");
00247 }
00248
00249 std::string desired_type = "";
00250 if (args.size() == 4) {
00251
00252 desired_type = args[3];
00253 }
00254
00255 if ( (desired_type == "") && ! i->valid()) {
00256 printf("Please specify type\n");
00257 delete i;
00258 } else if ( (desired_type != "") && (i->valid() && (desired_type != i->type())) ) {
00259 printf("The given type '%s' contradicts with type '%s' in config. "
00260 "Erase before setting with new type.\n", desired_type.c_str(), i->type());
00261 delete i;
00262 } else {
00263 if ( i->valid() ) desired_type = i->type();
00264
00265 if ( desired_type == "float" ) {
00266 char *endptr;
00267 float f = strtod(args[2], &endptr);
00268 if ( endptr[0] != 0 ) {
00269 printf("ERROR: '%s' is not a float\n", args[2]);
00270 } else {
00271 if ( ! set_def ) {
00272 netconf->set_float(args[1], f);
00273 } else {
00274 netconf->set_default_float(args[1], f);
00275 }
00276 }
00277 } else if ( (desired_type == "unsigned int") || (desired_type == "uint") ) {
00278 char *endptr;
00279 long int li = strtol(args[2], &endptr, 10);
00280 if ( (endptr[0] != 0) || (li < 0) ) {
00281 printf("ERROR: '%s' is not an unsigned int\n", args[2]);
00282 } else {
00283 if ( ! set_def ) {
00284 netconf->set_uint(args[1], li);
00285 } else {
00286 netconf->set_default_uint(args[1], li);
00287 }
00288 }
00289 } else if ( desired_type == "int" ) {
00290 char *endptr;
00291 long int li = strtol(args[2], &endptr, 10);
00292 if ( endptr[0] != 0 ) {
00293 printf("ERROR: '%s' is not an int\n", args[2]);
00294 } else {
00295 if ( ! set_def ) {
00296 netconf->set_int(args[1], li);
00297 } else {
00298 netconf->set_default_int(args[1], li);
00299 }
00300 }
00301 } else if ( desired_type == "bool" ) {
00302 bool valid = false;
00303 bool b;
00304 if ( strcasecmp("true", args[2]) == 0 ) {
00305 b = true;
00306 valid = true;
00307 } else if ( strcasecmp("false", args[2]) == 0 ) {
00308 b = false;
00309 valid = true;
00310 } else {
00311 printf("ERROR: '%s' is not a boolean.\n", args[2]);
00312 }
00313 if (valid) {
00314 if ( ! set_def ) {
00315 netconf->set_bool(args[1], b);
00316 } else {
00317 netconf->set_default_bool(args[1], b);
00318 }
00319 }
00320 } else if ( desired_type == "string" ) {
00321 if ( ! set_def ) {
00322 netconf->set_string(args[1], args[2]);
00323 } else {
00324 netconf->set_default_string(args[1], args[2]);
00325 }
00326 } else {
00327 printf("Invalid type: %s\n", desired_type.c_str());
00328 }
00329
00330 delete i;
00331
00332 printf("NEW:\n");
00333 i = netconf->get_value(args[1]);
00334 if ( i->next() ) {
00335 print_line(i);
00336 } else {
00337 printf("ERROR: value does not exist\n");
00338 }
00339 delete i;
00340
00341 }
00342 } else {
00343 printf("Usage: %s set <path> <value> [type]\n", argp.program_name());
00344 }
00345 } else if ((strcmp("set_comment", args[0]) == 0) ||
00346 (strcmp("set_default_comment", args[0]) == 0)) {
00347 bool set_def = (strcmp("set_default_comment", args[0]) == 0);
00348 if (args.size() >= 3) {
00349
00350
00351 if ( ! set_def ) {
00352 netconf->set_comment(args[1], args[2]);
00353 } else {
00354 netconf->set_default_comment(args[1], args[2]);
00355 }
00356
00357 } else {
00358 printf("Usage: %s set_(default_)comment <path> <value>\n", argp.program_name());
00359 }
00360 } else if ((strcmp("erase", args[0]) == 0) || (strcmp("erase_default", args[0]) == 0)) {
00361 bool erase_def = (strcmp("erase_default", args[0]) == 0);
00362 if (args.size() == 2) {
00363 printf("Erasing %svalue %s\n", (erase_def ? "default " : ""), args[1]);
00364 bool found = false;
00365 Configuration::ValueIterator *i = netconf->get_value(args[1]);
00366 if ( i->next() ) {
00367 print_header();
00368 print_line(i);
00369 found = true;
00370 } else {
00371 printf("No such value found!\n");
00372 }
00373 delete i;
00374 if ( found ) {
00375 if ( erase_def ) {
00376 netconf->erase_default(args[1]);
00377 } else {
00378 netconf->erase(args[1]);
00379 }
00380 i = netconf->get_value(args[1]);
00381 if ( i->next() ) {
00382 printf("Failed to erase %s (default vs. non-default?)\n", args[1]);
00383 } else {
00384 printf("Successfully erased %s\n", args[1]);
00385 }
00386 delete i;
00387 }
00388 } else {
00389
00390 printf("You must supply path argument\n");
00391 }
00392 } else if (strcmp("watch", args[0]) == 0) {
00393 try {
00394 netconf->set_mirror_mode(true);
00395 } catch (Exception &e) {
00396 e.print_trace();
00397 return -1;
00398 }
00399 print_header();
00400 netconf->lock();
00401 Configuration::ValueIterator *i = netconf->iterator();
00402 while ( i->next() ) {
00403 print_line(i, argp.has_arg("c"));
00404 }
00405 delete i;
00406 netconf->unlock();
00407 printf("------------------------------------------------------------------------------------\n");
00408 printf("Modifications since watching:\n");
00409 printf("------------------------------------------------------------------------------------\n");
00410 ConfigChangeWatcherTool ccwt(netconf, c);
00411 ccwt.run();
00412 } else if (strcmp("list", args[0]) == 0) {
00413 printf("Transmitting config from host... ");
00414 fflush(stdout);
00415 try {
00416 netconf->set_mirror_mode(true);
00417 } catch (Exception &e) {
00418 e.print_trace();
00419 return -1;
00420 }
00421 netconf->lock();
00422 printf("done\n");
00423 print_header();
00424 bool show_comments = argp.has_arg("c");
00425 if (argp.has_arg("a")) {
00426 printf("DEFAULT ENTRIES\n");
00427 Configuration::ValueIterator *i = netconf->iterator_default();
00428 while ( i->next() ) {
00429 print_line(i, show_comments);
00430 }
00431 delete i;
00432 printf("HOST-SPECIFIC ENTRIES\n");
00433 i = netconf->iterator_hostspecific();
00434 while ( i->next() ) {
00435 print_line(i, show_comments);
00436 }
00437 delete i;
00438 } else {
00439 Configuration::ValueIterator *i = netconf->iterator();
00440 while ( i->next() ) {
00441 print_line(i, show_comments);
00442 }
00443 delete i;
00444 }
00445 netconf->unlock();
00446 }
00447
00448
00449 printf("Cleaning up... ");
00450 fflush(stdout);
00451 delete netconf;
00452 c->disconnect();
00453
00454 delete c;
00455 printf("done\n");
00456
00457 return 0;
00458 }