1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
#include <uwsgi.h>
#include "client/dbclient.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_instance *ui;
// one for each mongodb imperial monitor
struct uwsgi_emperor_mongodb_state {
char *address;
char *collection;
char *json;
char *database;
char *username;
char *password;
char *predigest;
};
extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues) {
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
try {
// requested fields
mongo::BSONObj p = BSON( "name" << 1 << "config" << 1 << "ts" << 1 << "uid" << 1 << "gid" << 1 << "socket" << 1 );
mongo::BSONObj q = mongo::fromjson(uems->json);
std::unique_ptr<mongo::DBClientBase> conn;
conn = std::unique_ptr<mongo::DBClientBase> (new mongo::DBClientConnection(true, 0, uwsgi.socket_timeout));
dynamic_cast<mongo::DBClientConnection *>(conn.get())->connect(uems->address);
if (uems->database && uems->username && uems->password) {
std::string err;
if (conn->auth(uems->database, uems->username, uems->password, err, uems->predigest ? false : true) == false) {
uwsgi_log_verbose("[emperor-mongodb] unable to authenticate to db %s: %s\n", uems->database, err.c_str());
return;
}
}
// run the query
std::unique_ptr<mongo::DBClientCursor> cursor = conn->query(uems->collection, q, 0, 0, &p);
while(cursor.get() && cursor->more() ) {
mongo::BSONObj p = cursor->next();
// checking for an empty string is not required, but we reduce the load
// in case of badly strctured databases
const char *name = p.getStringField("name");
if (strlen(name) == 0) continue;
const char *config = p.getStringField("config");
if (strlen(config) == 0) config = NULL;
time_t vassal_ts = 0;
// ts must be a Date object !!!
mongo::BSONElement ts = p.getField("ts");
if (ts.type() == mongo::Date) {
vassal_ts = ts.date();
}
uid_t vassal_uid = 0;
gid_t vassal_gid = 0;
// check for tyrant mode
if (uwsgi.emperor_tyrant) {
int tmp_uid = p.getIntField("uid");
int tmp_gid = p.getIntField("gid");
if (tmp_uid < 0) tmp_uid = 0;
if (tmp_gid < 0) tmp_gid = 0;
vassal_uid = tmp_uid;
vassal_gid = tmp_gid;
}
const char *socket_name = p.getStringField("socket");
if (strlen(socket_name) == 0) socket_name = NULL;
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
}
// now check for removed instances
struct uwsgi_instance *c_ui = ui->ui_next;
while (c_ui) {
if (c_ui->scanner == ues) {
mongo::BSONObjBuilder b;
b.appendElements(q);
b.append("name", c_ui->name);
mongo::BSONObj q2 = b.obj();
cursor = conn->query(uems->collection, q2, 0, 0, &p);
if (!cursor.get()) return;
#ifdef UWSGI_DEBUG
uwsgi_log("JSON: %s\n", q2.toString().c_str());
#endif
if (!cursor->more()) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
}
}
catch ( mongo::DBException &e ) {
uwsgi_log("[emperor-mongodb] ERROR(%s/%s): %s\n", uems->address, uems->collection, e.what());
}
}
// setup a new mongodb imperial monitor
extern "C" void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *ues) {
// allocate a new state
ues->data = uwsgi_calloc(sizeof(struct uwsgi_emperor_mongodb_state));
size_t arg_len = strlen(ues->arg);
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
// parse args/ set defaults
uems->address = (char *) "127.0.0.1:27017";
uems->collection = (char *) "uwsgi.emperor.vassals";
uems->json = (char *) "";
if (arg_len > 10) {
uems->address = uwsgi_str(ues->arg+10);
char *comma = strchr(uems->address, ',');
if (!comma) goto done;
*comma = 0;
uems->collection = comma+1;
comma = strchr(uems->collection, ',');
if (!comma) goto done;
*comma = 0;
uems->json = comma+1;
}
done:
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
}
// setup a new mongodb imperial monitor (keyval based)
extern "C" void uwsgi_imperial_monitor_mongodb_init2(struct uwsgi_emperor_scanner *ues) {
// allocate a new state
ues->data = uwsgi_calloc(sizeof(struct uwsgi_emperor_mongodb_state));
size_t arg_len = strlen(ues->arg);
struct uwsgi_emperor_mongodb_state *uems = (struct uwsgi_emperor_mongodb_state *) ues->data;
// parse args/ set defaults
uems->address = (char *) "127.0.0.1:27017";
uems->collection = (char *) "uwsgi.emperor.vassals";
uems->json = (char *) "";
char *args = NULL;
if (arg_len <= 11) goto done;
args = ues->arg+11;
if (uwsgi_kvlist_parse(args, strlen(args), ',', '=',
"addr", &uems->address,
"address", &uems->address,
"server", &uems->address,
"collection", &uems->collection,
"coll", &uems->collection,
"json", &uems->json,
"database", &uems->database,
"db", &uems->database,
"username", &uems->username,
"password", &uems->password,
"predigest", &uems->predigest,
NULL)) {
uwsgi_log("[emperor-mongodb] invalid keyval syntax !\n");
exit(1);
}
done:
uwsgi_log("[emperor] enabled emperor MongoDB monitor for %s on collection %s\n", uems->address, uems->collection);
}
|