mod_netconf: copy-config support
copy-config operation is now supported by mod_netconf.
diff --git a/src/mod_netconf.c b/src/mod_netconf.c
index 23c3251..ffc0500 100644
--- a/src/mod_netconf.c
+++ b/src/mod_netconf.c
@@ -308,7 +308,7 @@
struct nc_session *session = NULL;
nc_rpc* rpc;
nc_reply* reply;
- char* data;
+ char* data = NULL;
struct nc_filter *f = NULL;
session = (struct nc_session *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
@@ -350,7 +350,8 @@
break;
default:
ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: unexpected rpc-reply");
- return (NULL);
+ data = NULL; /* error return code */
+ break;
}
nc_reply_free(reply);
@@ -361,6 +362,63 @@
}
}
+static int netconf_copyconfig(server_rec* server, apr_hash_t* conns, char* session_key, NC_DATASTORE source, NC_DATASTORE target)
+{
+ struct nc_session *session = NULL;
+ nc_rpc* rpc;
+ nc_reply* reply;
+ int retval = EXIT_SUCCESS;
+
+ session = (struct nc_session *)apr_hash_get(conns, session_key, APR_HASH_KEY_STRING);
+ if (session != NULL) {
+ /* create requests */
+ rpc = nc_rpc_copyconfig(source, target, NULL);
+ if (rpc == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: creating rpc request failed");
+ return (EXIT_FAILURE);
+ }
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "1");
+
+ /* send the request and get the reply */
+ nc_session_send_rpc (session, rpc);
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "2");
+ if (nc_session_recv_reply (session, &reply) == 0) {
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "3");
+ nc_rpc_free (rpc);
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "4");
+ if (nc_session_get_status(session) != NC_SESSION_STATUS_WORKING) {
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "5");
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: receiving rpc-reply failed");
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "6");
+ netconf_close(server, conns, session_key);
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "7");
+ return (EXIT_FAILURE);
+ }
+
+ /* there is error handled by callback */
+ return (EXIT_FAILURE);
+ }
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "8");
+ nc_rpc_free (rpc);
+ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "9");
+
+ switch (nc_reply_get_type (reply)) {
+ case NC_REPLY_OK:
+ retval = EXIT_SUCCESS;
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "mod_netconf: unexpected rpc-reply");
+ retval = EXIT_FAILURE;
+ break;
+ }
+ nc_reply_free(reply);
+ return (retval);
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, server, "Unknown session to process.");
+ return (EXIT_FAILURE);
+ }
+}
+
server_rec* clb_print_server;
int clb_print(const char* msg)
{
@@ -506,6 +564,20 @@
request = json_tokener_parse(buffer);
operation = json_object_get_int(json_object_object_get(request, "type"));
+ session_key = (char*) json_object_get_string(json_object_object_get(request, "session"));
+ /* DO NOT FREE session_key HERE, IT IS PART OF REQUEST */
+ if (operation != MSG_CONNECT && session_key == NULL) {
+ reply = json_object_new_object();
+ json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
+ json_object_object_add(reply, "error-message", json_object_new_string("Missing session specification."));
+ msgtext = json_object_to_json_string(reply);
+ send(client, msgtext, strlen(msgtext) + 1, 0);
+ json_object_put(reply);
+ /* there is some stupid client, so close the connection to give a chance to some other client */
+ close(client);
+ break;
+ }
+
switch (operation) {
case MSG_CONNECT:
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: Connect");
@@ -532,9 +604,7 @@
free(session_key);
break;
case MSG_GET:
- session_key = (char*)json_object_get_string(json_object_object_get(request, "session"));
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: get-config (session %s)", session_key);
- /* DO NOT FREE session_key HERE, IT IS PART OF REQUEST */
filter = json_object_get_string(json_object_object_get(request, "filter"));
@@ -542,22 +612,19 @@
if ((data = netconf_get(server, netconf_sessions_list, session_key, filter)) == NULL) {
json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
- json_object_object_add(reply, "error-message", json_object_new_string("get-config failed."));
- break;
+ json_object_object_add(reply, "error-message", json_object_new_string("get failed."));
+ } else {
+ json_object_object_add(reply, "type", json_object_new_int(REPLY_DATA));
+ json_object_object_add(reply, "data", json_object_new_string(data));
}
-
- json_object_object_add(reply, "type", json_object_new_int(REPLY_DATA));
- json_object_object_add(reply, "data", json_object_new_string(data));
break;
case MSG_GETCONFIG:
- session_key = (char*)json_object_get_string(json_object_object_get(request, "session"));
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: get-config (session %s)", session_key);
- /* DO NOT FREE session_key HERE, IT IS PART OF REQUEST */
source = json_object_get_string(json_object_object_get(request, "source"));
filter = json_object_get_string(json_object_object_get(request, "filter"));
- reply = json_object_new_object();
+ reply = json_object_new_object();
if (strcmp(source, "running") == 0) {
ds_type1 = NC_DATASTORE_RUNNING;
@@ -567,23 +634,58 @@
ds_type1 = NC_DATASTORE_CANDIDATE;
} else {
json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
- json_object_object_add(reply, "error-message", json_object_new_string("Invalid target repository type requested."));
+ json_object_object_add(reply, "error-message", json_object_new_string("Invalid source repository type requested."));
break;
}
if ((data = netconf_getconfig(server, netconf_sessions_list, session_key, ds_type1, filter)) == NULL) {
json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
json_object_object_add(reply, "error-message", json_object_new_string("get-config failed."));
+ } else {
+ json_object_object_add(reply, "type", json_object_new_int(REPLY_DATA));
+ json_object_object_add(reply, "data", json_object_new_string(data));
+ }
+ break;
+ case MSG_COPYCONFIG:
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: copy-config (session %s)", session_key);
+
+ source = json_object_get_string(json_object_object_get(request, "source"));
+ target = json_object_get_string(json_object_object_get(request, "target"));
+
+ reply = json_object_new_object();
+
+ if (strcmp(source, "running") == 0) {
+ ds_type1 = NC_DATASTORE_RUNNING;
+ } else if (strcmp(source, "startup") == 0) {
+ ds_type1 = NC_DATASTORE_STARTUP;
+ } else if (strcmp(source, "candidate") == 0) {
+ ds_type1 = NC_DATASTORE_CANDIDATE;
+ } else {
+ json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
+ json_object_object_add(reply, "error-message", json_object_new_string("Invalid source repository type requested."));
+ break;
+ }
+ if (strcmp(target, "running") == 0) {
+ ds_type2 = NC_DATASTORE_RUNNING;
+ } else if (strcmp(target, "startup") == 0) {
+ ds_type2 = NC_DATASTORE_STARTUP;
+ } else if (strcmp(target, "candidate") == 0) {
+ ds_type2 = NC_DATASTORE_CANDIDATE;
+ } else {
+ json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
+ json_object_object_add(reply, "error-message", json_object_new_string("Invalid target repository type requested."));
break;
}
- json_object_object_add(reply, "type", json_object_new_int(REPLY_DATA));
- json_object_object_add(reply, "data", json_object_new_string(data));
+ if (netconf_copyconfig(server, netconf_sessions_list, session_key, ds_type1, ds_type2) != EXIT_SUCCESS) {
+ json_object_object_add(reply, "type", json_object_new_int(REPLY_ERROR));
+ json_object_object_add(reply, "error-message", json_object_new_string("copy-config failed."));
+ } else {
+ json_object_object_add(reply, "type", json_object_new_int(REPLY_OK));
+ }
break;
case MSG_DISCONNECT:
- session_key = (char*)json_object_get_string(json_object_object_get(request, "session"));
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, server, "Request: Disconnect session %s", session_key);
- /* DO NOT FREE session_key HERE, IT IS PART OF REQUEST */
reply = json_object_new_object();
if (netconf_close(server, netconf_sessions_list, session_key) != EXIT_SUCCESS) {
@@ -610,13 +712,6 @@
} else {
break;
}
-
-#if 0
- case MSG_DATA:
- /* netconf data */
- handle_netconf_request(server, client, netconf_sessions_list, &buffer[1]);
- break;
-#endif
}
}
}
diff --git a/src/test-client.c b/src/test-client.c
index f9e099e..d0d887a 100644
--- a/src/test-client.c
+++ b/src/test-client.c
@@ -88,7 +88,7 @@
int main (int argc, char* argv[])
{
- json_object* msg = NULL, *reply;
+ json_object* msg = NULL, *reply = NULL;
const char* msg_text;
int sock;
struct sockaddr_un addr;
@@ -148,6 +148,20 @@
line[(strlen(line)-1)] = 0;
json_object_object_add(msg, "session", json_object_new_string(line));
} else if (strcmp(argv[1], "copy-config") == 0) {
+ msg = json_object_new_object();
+ json_object_object_add(msg, "type", json_object_new_int(MSG_COPYCONFIG));
+ printf("Session: ");
+ getline (&line, &len, stdin);
+ line[(strlen(line)-1)] = 0;
+ json_object_object_add(msg, "session", json_object_new_string(line));
+ printf("Source (running|startup|candidate): ");
+ getline (&line, &len, stdin);
+ line[(strlen(line)-1)] = 0;
+ json_object_object_add(msg, "source", json_object_new_string(line));
+ printf("Target (running|startup|candidate): ");
+ getline (&line, &len, stdin);
+ line[(strlen(line)-1)] = 0;
+ json_object_object_add(msg, "target", json_object_new_string(line));
} else if (strcmp(argv[1], "delete-config") == 0) {
} else if (strcmp(argv[1], "edit-config") == 0) {
} else if (strcmp(argv[1], "get") == 0) {
@@ -193,7 +207,10 @@
if (msg != NULL) {
msg_text = json_object_to_json_string(msg);
- printf("Sending: %s\n", msg_text);
+ if (json_object_object_get(msg, "pass") == NULL) {
+ /* print message only if it does not contain password */
+ printf("Sending: %s\n", msg_text);
+ }
send(sock, msg_text, strlen(msg_text) + 1, 0);
json_object_put(msg);
@@ -203,23 +220,29 @@
}
len = recv(sock, buffer, BUFFER_SIZE, 0);
- reply = json_tokener_parse(buffer);
- printf("Received:\n");
- json_object_object_foreach(reply, key, value) {
- printf("Key: %s, Value: ", key);
- switch(json_object_get_type(value)) {
- case json_type_string:
- printf("%s\n", json_object_get_string(value));
- break;
- case json_type_int:
- printf("%d\n", json_object_get_int(value));
- break;
- default:
- printf("\n");
- break;
- }
+ if (len > 0) {
+ reply = json_tokener_parse(buffer);
}
- json_object_put(reply);
+ printf("Received:\n");
+ if (reply == NULL) {
+ printf("(null)\n");
+ } else {
+ json_object_object_foreach(reply, key, value) {
+ printf("Key: %s, Value: ", key);
+ switch (json_object_get_type(value)) {
+ case json_type_string:
+ printf("%s\n", json_object_get_string(value));
+ break;
+ case json_type_int:
+ printf("%d\n", json_object_get_int(value));
+ break;
+ default:
+ printf("\n");
+ break;
+ }
+ }
+ json_object_put(reply);
+ }
close(sock);
free(line);