Author: tedross
Date: 2008-11-12 23:26:27 -0500 (Wed, 12 Nov 2008)
New Revision: 2791
Modified:
mgmt/trunk/sesame/cpp/etc/sesame.conf
mgmt/trunk/sesame/cpp/src/Makefile.am
mgmt/trunk/sesame/cpp/src/SysAgent.cpp
Log:
Added configuration and command line parsing.
Added example config file with comments.
The system agent is now fully functional.
Modified: mgmt/trunk/sesame/cpp/etc/sesame.conf
===================================================================
--- mgmt/trunk/sesame/cpp/etc/sesame.conf 2008-11-12 22:24:25 UTC (rev 2790)
+++ mgmt/trunk/sesame/cpp/etc/sesame.conf 2008-11-13 04:26:27 UTC (rev 2791)
@@ -1,4 +1,45 @@
##
## sesame configuration
##
-broker_url=amqp://localhost
+
+##===================
+## Broker Connection
+##===================
+
+##
+## Set the host and port of the broker that this agent shall attempt to
+## connect to. The port will default to the appropriate value based on the
+## protocol.
+##
+## For proto=tcp, the default port is 5672
+## proto=ssl, 5671
+## proto=rdma, 5672
+##
+#host=localhost
+#proto=tcp
+#port=5672
+
+##======================
+## Agent Authentication
+##======================
+
+##
+## Set the SASL mechanism (PLAIN by default), and the username and password
+## to be used when authenticating to the broker. If you wish to not store
+## the password in this configuration file, you may use pwd-file to point
+## to an access-restricted file containing the password.
+##
+#mech=PLAIN
+#uid=guest
+#pwd=guest
+#pwd-file=/etc/sesame/password
+
+##==============
+## Data Storage
+##==============
+
+##
+## Set the path to the directory where the sesame will store persistent data.
+##
+state-dir=.
+
Modified: mgmt/trunk/sesame/cpp/src/Makefile.am
===================================================================
--- mgmt/trunk/sesame/cpp/src/Makefile.am 2008-11-12 22:24:25 UTC (rev 2790)
+++ mgmt/trunk/sesame/cpp/src/Makefile.am 2008-11-13 04:26:27 UTC (rev 2791)
@@ -1,5 +1,7 @@
SUBDIRS = qmfgen
-AM_CXXFLAGS = -I$(QPID_DIR)/cpp/src -I$(QPID_DIR)/cpp/src/gen -Iqmfgen
+sesame_CXXFLAGS = -I$(QPID_DIR)/cpp/src -I$(QPID_DIR)/cpp/src/gen -Iqmfgen \
+ -DCONF_FILE=\"$(sysconfdir)/sesame.conf\" \
+ -DLOCSTATE_DIR=\"$(localstatedir)/sesame\"
include qmfgen/qmfgen.mk
Modified: mgmt/trunk/sesame/cpp/src/SysAgent.cpp
===================================================================
--- mgmt/trunk/sesame/cpp/src/SysAgent.cpp 2008-11-12 22:24:25 UTC (rev 2790)
+++ mgmt/trunk/sesame/cpp/src/SysAgent.cpp 2008-11-13 04:26:27 UTC (rev 2791)
@@ -28,11 +28,11 @@
{
ManagementAgent* agent;
_qmf::SysImage* mgmtObject;
- qpid::framing::Uuid sysId;
+ qpid::framing::Uuid uuid;
public:
- SysAgent(ManagementAgent* agent);
+ SysAgent(ManagementAgent* agent, const string& uuidFile);
~SysAgent() { mgmtObject->resourceDestroy(); }
ManagementObject* GetManagementObject(void) const
@@ -59,13 +59,27 @@
void getMem(Mem& mem);
};
-SysAgent::SysAgent(ManagementAgent* _agent) : agent(_agent)
+SysAgent::SysAgent(ManagementAgent* _agent, const string& uuidFile) : agent(_agent)
{
std::string sysname, nodename, release, version, machine;
// obtain or establish the system-id
- sysId.generate();
- mgmtObject = new _qmf::SysImage(agent, this, sysId);
+ ifstream input(uuidFile.c_str());
+ if (input.good()) {
+ input >> uuid;
+ input.close();
+ }
+
+ if (uuid.isNull()) {
+ uuid.generate();
+ ofstream output(uuidFile.c_str());
+ if (output.good()) {
+ output << uuid << endl;
+ output.close();
+ }
+ }
+
+ mgmtObject = new _qmf::SysImage(agent, this, uuid);
qpid::sys::SystemInfo::getSystemId (sysname,
nodename,
release,
@@ -150,12 +164,138 @@
}
}
+struct Option {
+ string placeholder;
+ string defaultVal;
+ string help;
+ string value;
+
+ Option() {}
+ Option(const string& p, const string& d, const string& h) :
+ placeholder(p), defaultVal(d), help(h), value(d) {}
+};
+
+static map<string, Option> options;
+
//==============================================================
// Main program
//==============================================================
ManagementAgent::Singleton* singleton;
+void usage()
+{
+ cerr << "Usage: sesame [OPTIONS]" << endl << endl;
+ for (map<string, Option>::iterator iter = options.begin();
+ iter != options.end(); iter++)
+ cerr << " --" << iter->first << " "
<< iter->second.placeholder <<
+ " (" << iter->second.defaultVal << ") "
<< iter->second.help << endl;
+ exit(1);
+}
+
+void configure(int argc, char** argv)
+{
+ // Check to see if the config file was overridden
+ for (int i = 1; i < argc; i++) {
+ string arg(argv[i]);
+ if (arg == "--config") {
+ i++;
+ if (i == argc)
+ usage();
+ options["config"].value = string(argv[i]);
+ }
+ if (arg == "--no-config")
+ options["config"].value = string();
+ if (arg == "--help")
+ usage();
+ }
+
+ // Open the config file, if present, and load its values as overrides
+ // to the defaults.
+ if (!options["config"].value.empty()) {
+ ifstream input(options["config"].value.c_str());
+ if (!input.good()) {
+ cerr << "Can't open config file: " <<
options["config"].value << endl;
+ exit(1);
+ }
+
+ while (!input.eof()) {
+ char line[512];
+ char* cursor;
+ char* val;
+
+ input.getline(line, 512);
+ if (input.fail() && !input.eof()) {
+ cerr << "Line too long in config file: " <<
options["config"].value << endl;
+ exit(1);
+ }
+
+ if (line[0] != '\0' && line[0] != '#') {
+ cursor = line;
+ while (*cursor != '\0' && *cursor != '=')
+ cursor++;
+ if (*cursor == '\0') {
+ cerr << "Missing value in config line: " <<
line << endl;
+ exit(1);
+ }
+ *cursor = '\0';
+ val = ++cursor;
+
+ map<string, Option>::iterator iter = options.find(line);
+ if (iter == options.end()) {
+ cerr << "Config file option '" << line
<< "' not known" << endl;
+ exit(1);
+ }
+
+ iter->second.value = string(val);
+ }
+ }
+
+ input.close();
+ }
+
+ // Run through the command line options and override the defaults and the config
file.
+ for (int i = 1; i < argc; i++) {
+ string arg(argv[i]);
+ if (arg == "--no-config")
+ continue;
+ if (arg.substr(0, 2) != "--") {
+ cerr << "Invalid argument: " << arg << endl;
+ usage();
+ }
+
+ map<string, Option>::iterator iter = options.find(arg.substr(2));
+ if (iter == options.end()) {
+ cerr << "Unknown option: " << arg << endl;
+ usage();
+ }
+
+ i++;
+ if (i == argc) {
+ cerr << "No value for option: " << arg << endl;
+ usage();
+ }
+
+ iter->second.value = string(argv[i]);
+ }
+}
+
+void getPassword()
+{
+ string file(options["pwd-file"].value);
+ if (file.empty())
+ return;
+
+ ifstream input(file.c_str());
+ if (!input.good()) {
+ cerr << "Can't read password file" << endl;
+ exit(1);
+ }
+
+ input >> options["pwd"].value;
+ input.close();
+}
+
void shutdown(int)
{
delete singleton;
@@ -165,23 +305,37 @@
int main_int(int argc, char** argv)
{
singleton = new ManagementAgent::Singleton();
- const char* host = argc>1 ? argv[1] : "127.0.0.1";
- int port = argc>2 ? atoi(argv[2]) : 5672;
-
signal(SIGINT, shutdown);
+ options["no-config"] = Option("", "",
"Don't read configuration file");
+ options["config"] = Option("FILE", CONF_FILE,
"Configuration file");
+ options["host"] = Option("ADDR", "localhost",
"Broker host name or IP address");
+ options["port"] = Option("N", "5672",
"Port for broker service");
+ options["proto"] = Option("NAME", "tcp",
"Protocol for broker communication");
+ options["mech"] = Option("NAME", "PLAIN",
"Authentication mechanism");
+ options["uid"] = Option("NAME", "guest",
"Authentication user name");
+ options["pwd"] = Option("PASSWORD", "guest",
"Authentication password");
+ options["pwd-file"] = Option("FILE", "",
"File containing password");
+ options["state-dir"] = Option("DIR", LOCSTATE_DIR,
"Directory for stored state");
+
+ configure(argc, argv);
+ getPassword();
+
// Create the qmf management agent
ManagementAgent* agent = singleton->getInstance();
- // Register the Qmf_example schema with the agent
+ // Register the schema with the agent
_qmf::Package packageInit(agent);
// Start the agent. It will attempt to make a connection to the
// management broker
- agent->init(string(host), port, 5, false, ".magentdata");
+ agent->init(options["host"].value,
::atoi(options["port"].value.c_str()), 5, false,
+ options["state-dir"].value + "/agentdata",
+ options["uid"].value, options["pwd"].value,
+ options["mech"].value, options["proto"].value);
// Allocate core object
- SysAgent core(agent);
+ SysAgent core(agent, options["state-dir"].value + "/uuid");
core.run();
}