BakBone Software SDK

API Programming Reference

  1. Overview
  2. The send_command() function
  3. The apply_config() function
  4. Compiling Software Against the API
  5. Appendix
    1. cdi_example_api.c

Overview

Originally released with version 3.3, the BakBone Software Programming API is used to customize the management of BakBone Software storage software availability products including NetVault:Replicator and NetVault:Replicator OnDemand.

This document contains detailed information on the usage and prototypes of the published API functions.

The send_command() function

The send_command() API function can be used to send commands via the management API to a server running BakBone Software software. Commands can be sent to a server to query information about the state of the running server. Commands can also be sent to change the state of the running server.

Prototype

int send_command(char *hostname, 
			int cmd, 
			void *arg, 
			size_t arg_sz,
			void *res, 
			size_t res_size);

Field Descriptions

send_command()
Parameter Type Description
hostname char * The hostname of the server that will receive the query or command.
cmd int

A valid command from the following list:

STATUS_GET_VERSION
STATUS_GET_LICENSE_OK
STATUS_GET_LICENSE_EXPIRES
STATUS_GET_KERNEL_MODULE_LOADED
STATUS_GET_CDI_SRV_RUNNING
STATUS_GET_REPSET_SRC_LIST
STATUS_GET_REPSET_DEST_LIST
STATUS_GET_REPSET_STATE
STATUS_GET_REPSET_REP_EVENTS
STATUS_GET_REPSET_PENDING_EVENTS
STATUS_GET_REPSET_PROGRESS_EVENTS
STATUS_GET_REPSET_TOTAL_FILES
CONFIG_START_CDI_SRV
CONFIG_STOP_CDI_SRV
CONFIG_RESTART_CDI_SRV
CONFIG_PAUSE_REPLICATION
CONFIG_RESUME_REPLICATION
arg void * Optional argument to cmd (Required for all STATUS_GET_REPSET commands.)
arg_sz size_t Size of corresponding optional arg variable. (Required for all STATUS_GET_REPSET commands.)
res void * The variable that will hold the result from the remote command
res_size size_t The size of buffer allocated for the result by the user

The apply_config() function

The apply_config() API function is used to define a configuration for the specified hostname running BakBone Software software.

Prototype

int apply_config(char *hostname, 
		char *to, 
		char *from, 
		char *global);

Field Descriptions

apply_config()
Parameter Type Description
hostname char * The hostname of the server that will receive the query or command.
to char * The <to> section of the configuration file on server hostname
from char * The <from> section of the configuration file on server hostname
global char * The <global> section of the configuration file on server hostname

Compiling Software Against the API

The BakBone Software management API is installed into $CDI_BASE_DIR/api/, where $CDI_BASE_DIR is the base installation directory for the software. To use the management API, #include the header file into your program, and provide the paths to the headers and shared libraries to your compiler, e.g.:

# gcc -I${CDI_BASE_DIR}/api/include/ -l${CDI_BASE_DIR}/api/lib/nvrapi.so myprog.c -o myprog

Appendix

The following sample code is provided to demonstrate possible usage of the API:

cdi_example_api.c

/*
 * nvr_example_api.c
 *
 * This sample code is provided AS IS, with no support or
 * warranties of any kind, including but not limited to
 * warranties of merchantability or fitness of any kind,
 * expressed or implied.
 *
 * www.backbone.com
 *
 * Compile with:
 *   gcc -I/usr/local/nvr/api/include/ -l/usr/local/cdi/api/lib/cdiapi.so -o cdi_example_api cdi_example_api.c
 */
#include <stdlib.h>
#include <stdio.h>
#include <libgen.h>
#include <unistd.h>
#include <nvr_mgmt_api.h>
void usage(char*);
int
main(int argc, char *argv[])
{
	char c;
	char *hostname      = NULL;
	char *repset        = NULL;
	int do_version      = 0,
	    license_ok      = 0,
	    license_expiry  = 0,
	    module_loaded   = 0,
	    nvr_srv         = 0,
	    pause           = 0,
	    resume          = 0,
	    start           = 0,
	    stop            = 0,
	    sourcelist      = 0,
	    destlist        = 0,
	    restart         = 0;
	char msg[255] = {'\0'};
	int ret, status;
	int query_status = 0;
	while ((c = getopt(argc, argv, "h:s:vlemdprwWSXR")) != EOF) {
		switch (c) {
			case 'h':
				hostname = optarg;
				break;
			case 'v':
				do_version = 1;
				break;
			case 'l':
				license_ok = 1;
				break;
			case 'e':
				license_expiry = 1;
				break;
			case 'm':
				module_loaded = 1;
				break;
			case 'd':
				nvr_srv = 1;
				break;
			case 'p':
				pause = 1;
				break;
			case 's':
				repset = optarg;
				break;
			case 'r':
				resume = 1;
				break;
			case 'w':
				sourcelist = 1;
				break;
			case 'W':
				destlist = 1;
				break;
			case 'S':
				start = 1;
				break;
			case 'X':
				stop = 1;
				break;
			case 'R':
				restart = 1;
				break;
			default:
				usage(argv[0]);
				exit(EXIT_FAILURE);
		}
	}
	if (!hostname) {
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}
	if (do_version) {
		ret = send_command(hostname, STATUS_GET_VERSION, 
				NULL, 0, msg, 255);
		if (ret == 0)
			printf("%s running s/w version %s\n", hostname, msg);
		else {
			printf("Unable to determine software version\n");
			query_status++;
		}
	}
	if (license_ok) {
		ret = send_command(hostname, STATUS_GET_LICENSE_OK, 
				NULL, 0, msg, 255);
		if (ret == 0)
			printf("License valid\n");
		else {
			printf("License not valid\n");
			query_status++;
		}
	}
	if (license_expiry) {
		ret = send_command(hostname, STATUS_GET_LICENSE_EXPIRES, 
				NULL, 0, msg, 255);
		if (ret == 0) {
			printf("%s's license expires in %s days\n", 
					hostname, msg);
		} else {
			printf("Unable to get license expiration\n");
			query_status++;
		}
	}
	if (module_loaded) {
		ret = send_command(hostname, STATUS_GET_KERNEL_MODULE_LOADED, 
				NULL, 0, msg, 255);
		if (ret == 0) {
			printf("%s has CDI kernel module loaded\n", hostname);
		} else {
			printf("CDI kernel module not loaded\n");
			query_status++;
		}
	}
	if (nvr_srv) {
		ret = send_command(hostname, STATUS_GET_CDI_SRV_RUNNING, 
				NULL, 0, &status, sizeof(status));
		if (ret == 0) {
			printf("%s has nvr_srv daemon running\n", hostname);
		} else {
			printf("nvr_srv daemon not running on %s\n", hostname);
			query_status++;
		}
	}
	if (pause) {
		ret = send_command(hostname, CONFIG_PAUSE_REPLICATION, 
				NULL, 0, NULL, 0);
		if (ret == 0) {
			printf("%s's replication is paused\n", hostname);
		} else {
			printf("unable to pause replication on %s\n", hostname);
			query_status++;
		}
	}
	if (repset) {
		ret = send_command(hostname, STATUS_GET_REPSET_REP_EVENTS,
				repset, strlen(repset), msg, 255);
		/*
		 * You must use IVAL to convert any character string that
		 * contains a numeric value to a numeric type.
		 */
		status = IVAL(msg, 0);
		if (ret == 0) {
			printf("%s/%s has had %d replication events\n",
				hostname, repset, status);
			 /*
			  * See above for the need to use IVAL 
			  */
			 send_command(hostname, 
					 STATUS_GET_REPSET_PENDING_EVENTS,
					 repset, strlen(repset), msg, 255);
			 status = IVAL(msg, 0);
			 printf("\t(%d items pending)\n", status);
			 send_command(hostname,
					 STATUS_GET_REPSET_PROGRESS_EVENTS,
					 repset, strlen(repset), msg, 255);
			 status = IVAL(msg, 0);
			 printf("\t(%d items in progress)\n", status);
			 send_command(hostname, STATUS_GET_REPSET_TOTAL_FILES,
				repset, strlen(repset), msg, 255);
			 status = IVAL(msg, 0);
			 printf("\t(%d total files)\n", status);
		} else {
			printf("Unable to get stats for %s/%s\n",
					hostname, repset);
			query_status++;
		}
	}
	if (resume) {
		ret = send_command(hostname, CONFIG_RESUME_REPLICATION, 
				NULL, 0, NULL, 0);
		if (ret == 0) {
			printf("%s's replication is resumed\n", hostname);
		} else {
			printf("Unable to resume on %s\n", hostname);
			query_status++;
		}
	}
	if (sourcelist) {
		ret = send_command(hostname, STATUS_GET_REPSET_SRC_LIST,
				NULL, 0, msg, 255);
		if (ret == 0) {
			printf("%s's source repsets are %s\n", hostname, msg);
		} else {
			printf("Unable to get list of source repsets\n");
			query_status++;
		}
	}
	if (destlist) {
		ret = send_command(hostname, STATUS_GET_REPSET_DEST_LIST,
				NULL, 0, msg, 255);
		if (ret == 0) {
			printf("%s's destination repsets are %s\n", 
					hostname, msg);
		} else {
			printf("Unable to get list of destination repsets\n");
			query_status++;
		}
	}
	if (stop) {
		ret = send_command(hostname, CONFIG_STOP_CDI_SRV, 
				NULL, 0, NULL, 0);
			if (ret == 0) {
				printf("replication stopped on %s\n", hostname);
			} else {
				printf("Unable to stop replication on %s\n", 
						hostname);
				query_status++;
			}
	}
	if (start) {	
		ret = send_command(hostname, CONFIG_START_CDI_SRV, 
				NULL, 0, NULL, 0);
		if (ret == 0) {
			printf("replication started on %s\n", hostname);
		} else {
			printf("Unable to start replication on %s\n");
			query_status++;
		}
	}
	if (restart) {	
		ret = send_command(hostname, CONFIG_RESTART_CDI_SRV, 
				NULL, 0, NULL, 0);
		if (ret == 0) {
			printf("replication restarted on %s\n", hostname);
		} else {
			printf("Unable to restart replication on %s\n");
			query_status++;
		}
	}
	return 0;
}
void
usage(char *prog)
{
	printf("Usage: %s -h [-v] [-l [-e]] [-m] [-d] [-p] [-s repset] [-r]\n",
			prog);
	printf("-h \t hostname\n");
	printf("-v \t Netvault software version number\n");
	printf("-l \t check license validity\n");
	printf("-e \t check license expiry\n");
	printf("-m \t check kernel module status\n");
	printf("-d \t check replication daemon status\n");
	printf("-p \t pause replication\n");
	printf("-s \t get repset statistics\n");
	printf("-p \t pause replication\n");
	printf("-r \t resume replication\n");
	printf("-w \t list source repsets\n");
	printf("-W \t list destination repsets\n");
	printf("-S \t start replication\n");
	printf("-X \t stop replication\n");
	printf("-R \t restart replication\n");
}