[Top] [Prev] [Next] [Bottom]


8 - Using the Database API Functions

This chapter describes the Site/SunNet/Domain Manager database API functions. The API functions allow you to do the following tasks: Example code segments are provided for each task. Refer to the man page for each function for a full description of syntax and returned values.

Before proceeding with this chapter, you should make sure that you have a thorough understanding of the Site/SunNet/Domain Manager database structures.


8.1 Building Your Program

The API functions are used in conjunction with a header file supplied with the product software. The header file netmgt_db.h defines the data structures for a cluster record buffer that is used with database operations. The cluster record buffer is used to hold a copy of a cluster record retrieved from the database or to hold a new cluster record while it is being created. When you add a new cluster record or modify an existing cluster record, the information in the cluster record buffer is written into the database. The header file also defines errors that can be returned by API functions.


8.2 Static and Dynamic Linking

You can link your application with libnetmgt_db and libnetmgt either statically or dynamically. Dynamically is preferable and recommended for the following reasons:

8.2.1 Dynamic Linking

Dynamic linking, as shown in the samples below, is the preferable and recommended linking method. When you dynamically link your program, you can include the following libnetmgt libraries:

NOTE - If you link with the libnetmgt_db.so library, the libnetmgt.so library must also be used, wit hlibnetmgt_db.so being listed before libnetmgt.so in the command line. The libnetmgt.so library may be used without the libnetmgt_db.so library.

8.2.1.1 Dynamic Linking for the Solaris 2.4 Environment

To link with the libraries provided with the Solaris 2.4 version of this product, you must link with the network services library (libnsl) and the internationalization library (libintl ). To dynamically link your application, follow this format:


host% cc myprog.c -o myprog -R /opt/SUNWconn/snm/lib -L /opt/SUNWconn/snm/lib -lnetmgt_db
-lnetmgt -lnsl
-lintl
 

Since the Solaris 2.x version of this product does not make links in /usr/lib, all Site/SunNet/Domain Manager applications should link with the -R option, as shown above. This avoids forcing the user to set the LD_LIBRARY_PATH variable at runtime.

8.2.1.2 Dynamic Linking for the Solaris 1.1.1 Environment

To dynamically link your application with the libraries provided with the Solaris 1.1.1 version of this product, follow this format:


host% cc myprog.c -o myprog -L /usr/snm/lib -lnetmgt_db -lnetmgt -lnsl
 

8.2.2 Static Linking

When you statically link your program, you can include the following libnetmgt libraries:


NOTE - If you link with the libnetmgt_db.a library, the libnetmgt.a library must also be used, wit hlibnetmgt_db.a being listed before libnetmgt.a in the command line. The libnetmgt.a library may be used without the libnetmgt_db.a library.

8.2.2.1 Static Linking for the Solaris 2.4 Environment

To link with the libraries provided with the Solaris 2.4 version of this product, you must link with the network services library (libnsl) and the internationalization library (libintl ). To statically link your application, follow this format:


host% cc myprog.c -o myprog -L /opt/SUNWconn/snm/lib -Bstatic -lnetmgt_db -lnetmgt -lnsl
-lintl -Bdynamic -ldl
 

If you use the static method, you must specifically link in libdl.

8.2.2.2 Static Linking in a Solaris 1.1.1 Environment

To statically link your application with the libraries provided for the Solaris 1.1 version of this product, follow this format:


host% cc myprog.c -o myprog -L /usr/snm/lib -Bstatic -lnetmgt_db -lnetmgt -lnsl
-lintl -Bdynamic -ldl
 

If you use the static method, you must specifically link in libdl.


8.3 Error Handling

Most functions return True (1) or False (0) values upon completion. If a value of False is returned, an error has occurred. If any error occurs during the execution of a function, the external variable snm_error is set to the error number that indicates the cause of the error. Errors are defined in the header file netmgt_db.h. See the snm_error(3N) man page for error codes and explanations.


8.4 Opening the Database

The snmdb_open function is used to open the database. The database must be located in the directory specified by the database keyword in the snm.conf file. (The snm.conf file is located in /etc for the Solaris 1.1.1 version of this product, and in /etc/opt/SUNWconn/snm for the Solaris 2.4 version.) If there is no directory specified by the database keyword, then the database is located in the following directory: The database that is opened is the file db. <name>, where <name> is the name specified by the environment variable SNM_NAME, or the login user name is SNM_NAME is not specified. You should call snmdb_open() before you perform any database operations.

The following is an example of how to call snmdb_open() .


if (!snmdb_open())    exit(1);
 


8.5 Locking and Unlocking the Database

The database should be locked while you are writing information to the database. Locking the database is not necessary while you are reading information from the database or while you are performing operations on the cluster record buffer. Locking the database prevents other applications, such as the Console, from making changes to the database. If your program does not lock the database, you should make sure that there are no other active applications that can make changes to the database.


NOTE - While the database is locked, Console users cannot perform any operations (such as sending and viewing requests) from the Console. Therefore, you should minimize the time that the database is locked. snmdb_lock allows you the option of displaying a clock on the Console while the database is locked.
The snmdb_lock() and snmdb_unlock() functions lock and unlock the database. Call snmdb_lock() to lock the database before you make changes to the database. After the database updates are done, you should call snmdb_unlock() to release the lock.


NOTE - The lock and unlock functions cause low-priority trap reports to be generated when elements are added, changed, or deleted in the database. These trap reports are sent to the event dispatcher, which then forwards the reports to registered management applications. See
Section 2.4, "Trap Reports," on page 2-4 , for more information.
The following is an example of how to call snmdb_lock() and snmdb_unlock().


if (snmdb_lock(TRUE, TRUE)) {
   ......
   /* update the database record(s) */
   ......
   if (!snmdb_unlock())
     printf("Error: unable to unlock the database.\n");
}
else
   printf("Error: unable to lock the database. error = %d\n",
         snm_error);
 


8.6 Retrieving Element Information from the Database

The functions used to retrieve database information fall into two sets: Each of these sets of functions is described in the following sections.


NOTE - The examples shown in the following sections are program fragments only. A complete program example is included in the product structure in thefile view_db.c in the API_examples directory.

8.6.1 Retrieving Information for a Single Element

To retrieve information about a single element from the database, you must first read the element cluster record into the cluster record buffer by calling snmdb_read. You can then retrieve any of the records contained in an element's cluster record. See the Administration Guide for information on cluster records. For agent and membership (view) records, you can either retrieve an enumerated list of the agent or view records or you can retrieve a specific agent or view record for the element.


NOTE - A call to snmdb_read initializes the cluster record buffer; therefore, you do not need to clear the buffer before reading subsequent cluster records into the internal buffer.
To retrieve a piece of element information for a single element, do the following:


1. Call snmdb_read(). Before you try to get any element information, you must call snmdb_read() to load the element record into the cluster record buffer.


2. Call one or more of the following functions:

3. For enumerated lists (agents, connections, or views), call snmdb_free_list() to free the storage allocated for the enumerated information.
The following examples assume that an element named "andrew" is defined in the database with the following information:


record component.ss1 (          # sparcstation 1
  string[32] Name
  string[40] IP_Address
  string[40] User
  string[40] Location
  string[80] Description
)

cluster(
  component.ss1 ( andrew 129.144.44.81 "Alice Wang" "Building   #14" "SunNet Manager Engineer" )
  glyphColor ( 255 221 0 )
  agent ( diskinfo )
  agent ( etherif )
  agent ( hostif )
  agent ( hostmem )
  agent ( iproutes )
  proxy ( concord-mib"" )
  proxy ( hostperf"" )
  proxy ( ippath"" )
  membership ( SunNetMgr 170 120 0 )
  membership ( Home 150 120 0 )
  connect ( swap )
  connect ( golden )
)
 

In the header file netmgt_db.h , the data type of the cluster record buffer is defined as:


typedef struct {
        unsigned char data[SNMBUFFERSIZE];
} snmdb_buffer;
 

The following code segment shows how to retrieve information on the element "andrew:"




snmdb_buffer buf;       /*cluster record buffer of element */
int red, green, blue;   /* color values */
int isproxy;    /* indicator - whether agent is proxy */
int x, y;               /* x, y coordinates in a view */
char name[128];         /* name buffer */

/* first, we load the element record into the cluster record
   buffer for `andrew' */
if (!snmdb_read("andrew", &buf)) { /* read error */
  printf("snmdb_read() failed, error = %d\n", snm_error);
  return;
}

/* get the type of the element, in this case, it should
   return the string "component.ss1" */
printf("The type of element `andrew' is %s\n",
       (char *)snmdb_get_element_type(&buf));

/* get the value of property `User', `Location', and
   `Description' */
printf("For element `andrew': `User' field = %s\n",
       snmdb_get_property(&buf, "User", 0).db_string);
printf("        `Location' field = %s\n",
       snmdb_get_property(&buf, "Location", 0).db_string);
printf("        `Description' field = %s\n",
       snmdb_get_property(&buf, "Description", 0).db_string);

/* get the color of it */
/* colors are represented in RGB numbers, snmdb_get_color()
   will return the RGB numbers of the element glyph */
/* in this case, red = 255, green = 221, blue = 0 */
if (snmdb_get_color(&buf, &red, &green, &blue))
  printf("Color values are: %d, %d, %d\n", red, green, blue);
else
  printf("There is no color defined for element.\n");

/* get agent information for agent `hostperf' */
if (snmdb_get_agent(&buf, "hostperf", &isproxy, name)) {
  if (isproxy)
    printf("hostperf is proxy, proxy name = %s\n", name);
 




  else
    printf("hostperf is not proxy\n");
}
else
  printf("agent `hostperf' is not running on element.\n");

/* get the location of element in view `SunNetMgr' */
if (snmdb_get_view(&buf, "SunNetMgr", &x, &y, NULL, NULL)) {
  printf("Location of `andrew' in view `SunNetMgr' is :\n");
  printf(" x = %d, y = %d\n", x, y);
}
else
  printf("Element is not in view `SunNetMgr', error = %d\n",
         snm_error);
 

The following code segment shows how to get all the agents that apply to the target element, how to get all the element names that the target element is connected to, and how to get all the views in which the target element exists:


snmdb_buffer buf;            /* buffer of element */
char **names;                /* pointer to the enumerated list */
char **str;                  /* temp. pointer */

/* first, we load the element record into the cluster record
   buffer for `andrew' */
if (!snmdb_read("andrew", &buf)) { /* read error */
  printf("snmdb_read() failed, error = %d\n", snm_error);
  return;
}

/* get all the agent names that run on (or apply to)
   `andrew' */
if ((names = snmdb_enumerate_agents(&buf)) == NULL) {
  printf("Error: unable to enumerate agents, error = %d\n",
         snm_error);
  return;
}
/* got the enumerated list successfully, print the list */
for (str = names; *str; str++)
 




  printf("agent `%s' found\n", *str);
/* remember to free the space used */
snmdb_free_list(names);

/* get all the element names that `andrew' is connected to */
if ((names = snmdb_enumerate_connections(&buf)) == NULL) {
  printf("Error: unable to enumerate connections, error = %d\n",
        snm_error);
  return;
}
/* got the enumerated list successfully, print the list */
for (str = names; *str; str++)
  printf("connected to `%s'\n", *str);
/* remember to free the space used */
snmdb_free_list(names);

/* get all the view names that `andrew' exists in */
if ((names = snmdb_enumerate_views(&buf)) == NULL) {
  printf("Error: unable to enumerate views, error = %d\n",
         snm_error);
  return;
}/* got the enumerated list successfully, print the list */
for (str = names; *str; str++)
  printf("element exists in view `%s'\n", *str);
/* remember to free the space used */
snmdb_free_list(names);
 

8.6.2 Retrieving Elements of a Given Type

To retrieve the names of elements of a given type in a particular view or in all views, do the following:


1. Call snmdb_enumerate_elements() to specify which element to enumerate in a particular view or in all views. This function also initializes storage for the list of elements.


2. Call snmdb_get_next_element() multiple times to retrieve the names of the elements in the list.


3. Call snmdb_free_enumeration_handle() to free the storage allocated for the enumerated element names.
The following code segment shows how to retrieve all element names in all views:


snmdb_handle *handle;     /* pointer to the enumerated list */
char *str;                /* temp. pointer */

if (!(handle = snmdb_enumerate_elements(NULL, NULL))) {
  printf("No element in any view\n");
  return;
}

printf("Elements of all types in all views are:\n");
while (str = snmdb_get_next_element(handle))
  printf("element = %s\n", str);
printf("end of list\n");

/* remember to free the space */
snmdb_free_enumeration_handle(handle);
 

The following code segment shows how to retrieve all element names of a given type in one particular view.


snmdb_handle *handle;    /* pointer to the enumerated list */
char *str;               /* temp. pointer */

if (!(handle =
      snmdb_enumerate_elements("SunNetMgr", "component.ss1"))) {
  printf("No element of type `component.ss1' exists in view.\n");
  return;
}

printf("Elements of type `component.ss1' in view   `SunNetMgr':\n");
while (str = snmdb_get_next_element(handle))
  printf("element = %s\n", str);
printf("end of view\n");

/* remember to free the space */
snmdb_free_enumeration_handle(handle);
 


8.7 Adding a New Element Instance into the Database

You can add new element instances to the database. To add a new element instance, you first initialize the cluster record buffer, then create one or more records that make up the element cluster record. Then, you write the cluster record from the buffer to the database. Note that in the cluster record you must define at least one view in which the element will reside. Otherwise, an error is returned and the element is not added to the database.


NOTE - The element <type> for the element you are adding must be defined in a schema file; there is no API for adding a new element <type> .

NOTE - See the Administration Guide for information on adding a new element types.
To add a new element into the database, do the following:


1. Call snmdb_init_buffer() . You need to call snmdb_init_buffer() to initialize the cluster record buffer for the new element.


2. Call one or more of the following functions:

3. Call snmdb_add() to add the new element to the database. You can optionally lock the database by calling snmdb_lock()before callingsnmdb_add(). If the element is being added to a view that is currently displayed by the Console, call snmdb_lock() with its first parameter set to TRUE. This causes the Console to update its display when the element is added to the database. (Otherwise, the Console user must leave the view and then return to the view to see the new element.) Remember to unlock the database with snmdb_unlock() .
The following code segment shows how to add a new element "andrew". A complete program example is included in the product structure in the file add_db.c in the API_examples directory.




snmdb_buffer buf;         /* buffer of element */

/* initialize the cluster record buffer of the element */
if (!snmdb_init_buffer("andrew", "component.ss1", &buf)) {
  printf("snmdb_init_buffer() failed, error = %d\n",
         snm_error);
  return;
}

/* set the property */
if (!snmdb_set_property(&buf, "User", "test machine") ||
    !snmdb_set_property(&buf, "Location", "Building 14")) {
  printf("snmdb_set_property() failed, error = %d\n",
         snm_error);
  return;
}

/* set the color of the element */
snmdb_set_color(&buf, 100, 220, 0);

/* add a non-proxy and a proxy agent */
if (!snmdb_add_agent(&buf, "hostif", NULL) ||
     !snmdb_add_agent(&buf, "hostperf", "andrew")) {
  printf("snmdb_add_agent() failed, error = %d\n",
         snm_error);
  return;
}

/* add a connection to another element */
/* Note: the element you want to connect to should be a
         valid element name that exists in the database */
if (!snmdb_add_connection(&buf, "swap")) { /* error */
  printf("snmdb_add_connection() failed, error = %d\n",
         snm_error);
  return;
}

 




/* add the element `andrew' into the view `SunNetMgr' */
if (!snmdb_add_to_view(&buf, "SunNetMgr", 10, 50, 0, 0, 0)) {
  printf("snmdb_add_to_view() failed, error = %d\n",
         snm_error);
  return;
}
/* now we're ready to add the element to the database */
snmdb_lock (TRUE, FALSE);
if (!snmdb_add(&buf)) { /* error */
  printf("snmdb_add() failed, error = %d\n", snm_error);
  snmdb_unlock();
  return;
}
/* element added successfully */
snmdb_unlock();
 


8.8 Deleting an Element Instance from the Database

The function to delete an element instance operates directly on the database; the cluster record buffer is not used. You delete an element using snmdb_delete() . Note that you will not be able to delete an element if its subview is not empty.

If an element is being deleted from a view that is currently displayed by the Console, call snmdb_lock() with its first parameter set to TRUE . This causes the Console to update its display when the element is deleted. (Otherwise, the Console user must leave the view and then return to the view to see the element deleted.) Remember to unlock the database with snmdb_unlock() .

The following code segment shows how to delete the element "andrew" from the database. A complete program example is included in the product structure in the file del_db.c in the API_examples directory.


if (!snmdb_delete("andrew")) { /* unable to delete it */
  if (snm_error == SNMDB_SUBVIEW_IS_NOT_EMPTY)
    printf("Error: element's subview is not empty.\n");
  else
    printf("Error: unable to delete element, error = %d\n",
           snm_error);
}
/* element is deleted successfully */
 


8.9 Modifying an Element in the Database

To modify an element instance, the element's cluster record is first read into the cluster record buffer. After modifications are made to the records in the cluster record, the revised cluster record is written from the buffer back to the database.

To modify an element, do the following:


1. Call snmdb_read(). Before you try to change any element information, you must call snmdb_read() to load the element record into the cluster record buffer.


2. Call one or more of the following functions:

3. Call snmdb_update() to write the updated element back to the database. You can optionally lock the database by calling snmdb_lock() before callingsnmdb_update(). If the element is being modified in a view that is currently displayed by the Console, call snmdb_lock() with its first parameter set to TRUE. This causes the Console to update its display when the element is modified. (Otherwise, the Console user must leave the view and then return to the view to see the element modifications.) Remember to unlock the database with snmdb_unlock().
Note that you can make multiple changes to an element at a time. The changed information is written to the cluster record buffer. snmdb_update() writes the contents of the buffer to the database.

The following code segment shows how to update the element "andrew". A complete program example is included in the product structure in the file mod_db.c in the API_examples directory.




snmdb_buffer buf;	/* cluster record buffer of element */

/* first, we load the element record into the cluster record
   buffer for element `andrew' */
if (!snmdb_read("andrew", &buf)) { /* read error */
  printf("snmdb_read() failed, error = %d\n", snm_error);
  return;
}

/* modify the property value */
if (!snmdb_set_property(&buf, "User", "Admin System")) {
  printf("snmdb_set_property() failed, error = %d\n",
         snm_error);
  return;
}

/* add the element `andrew' into the view `SunNetMgr' */
if (!snmdb_add_to_view(&buf, "SunNetMgr", 10, 50, 0, 0, 0)) {
  printf("snmdb_add_to_view() failed, error = %d\n",
         snm_error);
  return;
}

/* delete the element `andrew' from view `Engineering' */
if (!snmdb_delete_from_view(&buf, "Engineering")) {
  printf("snmdb_delete_from_view() failed, error = %d\n",
         snm_error);
  return;
}

/* delete the connection between `andrew' and `swap' */
if (!snmdb_delete_connection(&buf, "swap")) {
  printf("snmdb_delete_connection() failed, error = %d\n",
         snm_error);
  return;
}

 




/* delete the agent record which describes `hostif' runs
   on the element */
if (!snmdb_delete_agent(&buf, "hostif")) {
  printf("snmdb_delete_agent() failed, error = %d\n",
         snm_error);
  return;
}
/* delete the color record, use default color */
snmdb_delete_color(&buf);

/* now we write the updated element back to the database */
if (!snmdb_update(&buf)) {
  printf("snmdb_update() failed, error = %d\n", snm_error);
  return;
}
/* element is updated successfully */
 


8.10 Saving Database Records to an ASCII File

You can save an element cluster record that has been read into the cluster record buffer by calling snmdb_save_element() . Note that because this function only operates on a single element at a time and it does not save request instances, it is not equivalent to using the Save option in the Console's File menu. See Section 8.12, "Saving the Runtime Database to an ASCII File ," if you want to save the entire database.

You can save all the element instances in a database to an ASCII file by enumerating through all the elements in the database, then reading and saving each element. This is shown in the example below.


/* Open the output file. */
if (!(fptr = fopen(outfile, "w"))) {
    printf("Cannot open %s for writing.\n", outfile);
    exit(1);
}
/* Enumerate through all the elements in the database. */
if (!(handle = snmdb_enumerate_elements(NULL, NULL))) {
  printf("No element found in the database.\n");
  exit(1);
}
 
/* Loop through the element records and save them into output 
file. */
while (name = snmdb_get_next_element(handle)) {
  if (!snmdb_read(name, &buf))
    printf("snmdb_read() failed, skipping element `%s'\n", name);
  if (!snmdb_save_element(&buf, fptr)) 
    printf("snmdb_save_element() failed, snm_error = %d\n", 
snm_error);
}
/* Free the enumerator handle. */
snmdb_free_enumeration_handle(handle);
 


8.11 Loading a Database File into the Console

You can load a database file into a Console session by calling snmdb_console_load() . Database load is accomplished through an RPC call to the Console. Note that the Console must be running. See the snmdb_console_load(3N) man page for information about this function.


8.12 Saving the Runtime Database to an ASCII File

You can have the Console save all element and request instances in its runtime database to a specified file in ASCII MDB form by calling snmdb_console_save_components() . Saving the runtime database is accomplished through an RPC call to the Console. This call has a three parameters: the path name of the file in which the MDB is to be saved, a pointer to an integer for returned RPC error codes, and a pointer to an integer for returned Console errors. Note that the Console must be running. See the snmdb_console_save_component(3N) man page for information about this function.

[Top] [Prev] [Next] [Bottom]

Copyright 1996 Sun Microsystems, Inc., 2550 Garcia Ave., Mtn. View, CA 94043-1100 USA. All Rights Reserved