equilibrium-mgmt_config.c

Go to the documentation of this file.
00001 /*
00002  * $Id: equilibrium-mgmt_config.c 346460 2009-11-14 05:06:47Z ssiano $
00003  *
00004  * This code is provided as is by Juniper Networks SDK Developer Support.
00005  * It is provided with no warranties or guarantees, and Juniper Networks
00006  * will not provide support or maintenance of this code in any fashion.
00007  * The code is provided only to help a developer better understand how
00008  * the SDK can be used.
00009  * 
00010  * Copyright (c) 2008, Juniper Networks, Inc.
00011  * All rights reserved.
00012  */
00013 
00021 #include <sync/common.h>
00022 #include <ddl/dax.h>
00023 #include "equilibrium-mgmt_config.h"
00024 #include "equilibrium-mgmt_conn.h"
00025 #include "equilibrium-mgmt_logging.h"
00026 
00027 #include EQUILIBRIUM_OUT_H
00028 
00029 /*** Constants ***/
00030 
00031 #define MAX_SVC_SETID                       0xFFFF  
00032 
00033 #define DDLNAME_SERVICE_SET_IDENT "service-set-name" 
00034 #define DDLNAME_EXTENTION_SERVICE_IDENT "service-name" 
00035 #define DDLNAME_INTERFACE_SERVICE "interface-service" 
00036 #define DDLNAME_INTERFACE_SERVICE_SVC_INT "service-interface" 
00037 
00038 
00039 /*** Data Structures ***/
00040 
00041    
00045 const char * equilibrium_service_prefix = "equilibrium-";
00046 
00052 typedef struct eq_app_key_s {
00053     in_addr_t addr;   
00054     uint16_t  port;   
00055     TAILQ_ENTRY(eq_app_key_s) entries; 
00056 } eq_app_key_t;
00057 
00061 typedef TAILQ_HEAD(, eq_app_key_s) eq_app_key_set_t;
00062 
00067 typedef struct eq_ssrb_s {
00068     patnode    node;              
00069     junos_kcom_pub_ssrb_t ssrb;   
00070 } eq_ssrb_t;
00071 
00072 static patroot   services_conf;      
00073 static patroot   ssrb_conf;          
00074 
00075 static eq_serviceset_t * current_svc_set = NULL; 
00076 static eq_app_t *        current_app = NULL;  
00077 
00078 
00079 /*** STATIC/INTERNAL Functions ***/
00080 
00081 
00086 PATNODE_TO_STRUCT(ssrb_entry, eq_ssrb_t, node)
00087 
00088 
00089 
00093 PATNODE_TO_STRUCT(service_entry, eq_serviceset_t, node)
00094 
00095 
00100 PATNODE_TO_STRUCT(app_entry, eq_app_t, node)
00101 
00102 
00119 static eq_serviceset_t *
00120 update_service_set(const char * ss_name,
00121                    const char * svc_name,
00122                    const char * svc_int_name)
00123 {
00124     eq_serviceset_t * service_set = NULL;
00125     
00126     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00127     
00128     // check if we know about this service-set
00129     service_set = service_entry(patricia_get(&services_conf,
00130                     strlen(ss_name) + 1, ss_name));
00131     
00132     if(service_set == NULL) {
00133         service_set = calloc(1, sizeof(eq_serviceset_t));
00134         INSIST(service_set != NULL);
00135         service_set->svc_set_id = -1; // set it to be invalid
00136         strncpy(service_set->svc_set_name, ss_name, MAX_SVC_SET_NAME);
00137 
00138         // Add to patricia tree
00139         patricia_node_init_length(&service_set->node, strlen(ss_name) + 1);
00140 
00141         if(!patricia_add(&services_conf, &service_set->node)) {
00142             junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s: Failed to add "
00143                     "service set to configuration", __func__);
00144         }
00145     }
00146     
00147     strncpy(service_set->svc_int_name, svc_int_name, MAX_SVC_INT_NAME);
00148     strncpy(service_set->ext_svc_name, svc_name, MAX_SVC_NAME);
00149     
00150     return service_set;
00151 }
00152 
00153 
00175 static eq_app_t *
00176 update_application(const char * name,
00177                    in_addr_t address,
00178                    uint16_t port,
00179                    eq_smon_t * server_monitor,
00180                    uint16_t session_timeout)
00181 {
00182     eq_app_t * app;
00183     
00184     INSIST_ERR(current_svc_set != NULL);
00185     
00186     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00187     
00188     // check if any applications config exists
00189     if(current_svc_set->applications == NULL) {
00190         // if not, init it
00191         current_svc_set->applications = 
00192             patricia_root_init(NULL, FALSE, MAX_APP_NAME, 0);
00193     }
00194     
00195     app = app_entry(patricia_get(current_svc_set->applications,
00196             strlen(name) + 1, name));
00197     
00198     if(app == NULL) {
00199         app = calloc(1, sizeof(eq_app_t));
00200         INSIST(app != NULL);
00201         strncpy(app->application_name, name, MAX_APP_NAME);
00202 
00203         // Add to patricia tree
00204         patricia_node_init_length(&app->node, strlen(name) + 1);
00205 
00206         if(!patricia_add(current_svc_set->applications, &app->node)) {
00207             junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s: Failed to add "
00208                     "application to configuration", __func__);
00209             return NULL;
00210         }
00211     }
00212     
00213     app->application_addr = address;
00214     app->application_port = port;
00215     app->session_timeout = session_timeout;
00216     
00217     if(app->server_mon_params == NULL) {
00218         app->server_mon_params = server_monitor;
00219         
00220         if(server_monitor == NULL) {
00221             notify_application_update(current_svc_set->svc_set_name,
00222                 name, address, port, session_timeout, 0, 0, 0, 0);
00223         } else {
00224             notify_application_update(current_svc_set->svc_set_name,
00225                 name, address, port, session_timeout,
00226                 server_monitor->connection_interval,
00227                 server_monitor->connection_timeout,
00228                 server_monitor->timeouts_allowed,
00229                 server_monitor->down_retry_interval);
00230         }
00231     } else {
00232         if(server_monitor == NULL) {
00233             free(app->server_mon_params);
00234             app->server_mon_params = NULL;
00235             
00236             notify_application_update(current_svc_set->svc_set_name,
00237                 name, address, port, session_timeout, 0, 0, 0, 0);
00238         } else {
00239             app->server_mon_params->connection_interval = 
00240                 server_monitor->connection_interval;
00241             app->server_mon_params->connection_timeout = 
00242                 server_monitor->connection_timeout;
00243             app->server_mon_params->timeouts_allowed = 
00244                 server_monitor->timeouts_allowed;
00245             app->server_mon_params->down_retry_interval = 
00246                 server_monitor->down_retry_interval;
00247             
00248             notify_application_update(current_svc_set->svc_set_name,
00249                 name, address, port, session_timeout,
00250                 server_monitor->connection_interval,
00251                 server_monitor->connection_timeout,
00252                 server_monitor->timeouts_allowed,
00253                 server_monitor->down_retry_interval);
00254         }
00255     }
00256     
00257     return app;
00258 }
00259 
00260 
00267 static void
00268 update_server(in_addr_t server_address)
00269 {
00270     eq_server_t * server = NULL;
00271     
00272     INSIST_ERR(current_app != NULL);
00273     INSIST_ERR(current_svc_set != NULL);
00274 
00275     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00276     
00277     if(current_app->servers == NULL) {
00278         current_app->servers = malloc(sizeof(server_list_t));
00279         INSIST(current_app->servers != NULL);
00280         TAILQ_INIT(current_app->servers);
00281     }
00282     
00283     server = calloc(1, sizeof(eq_server_t));
00284     INSIST(server != NULL);
00285     
00286     server->server_addr = server_address;
00287     TAILQ_INSERT_TAIL(current_app->servers, server, entries);
00288     
00289     notify_server_update(current_svc_set->svc_set_name,
00290             current_app->application_name, server->server_addr);
00291 }
00292 
00293 
00300 static void
00301 delete_server(in_addr_t server_address)
00302 {
00303     eq_server_t * server = NULL;
00304     
00305     INSIST_ERR(current_app != NULL);
00306     INSIST_ERR(current_svc_set != NULL);
00307     
00308     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00309     
00310     if(current_app->servers != NULL) {
00311         server = TAILQ_FIRST(current_app->servers);
00312         while(server != NULL) {
00313             if(server->server_addr == server_address) {
00314                 TAILQ_REMOVE(current_app->servers, server, entries);
00315                 
00316                 notify_server_delete(current_svc_set->svc_set_name,
00317                         current_app->application_name, server->server_addr);
00318                 
00319                 free(server);
00320                 break;
00321             }
00322             server = TAILQ_NEXT(server, entries);
00323         }
00324     }
00325 }
00326 
00327 
00341 static void
00342 delete_application(patroot * apps, eq_app_t ** application, boolean notify)
00343 {
00344     eq_app_t * app = *application;
00345     eq_server_t * server = NULL;
00346     
00347     if(notify) {
00348         INSIST_ERR(current_svc_set != NULL);
00349     }
00350     
00351     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00352     
00353     // Remove app from patricia tree
00354     if (!patricia_delete(apps, &app->node)) {
00355         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF,
00356                 "%s: Deleting application failed", __func__);
00357         return;
00358     }
00359     
00360     if(app->server_mon_params != NULL) {
00361         free(app->server_mon_params);
00362     }
00363     
00364     if(app->servers != NULL) {
00365         while((server = TAILQ_FIRST(app->servers)) != NULL) {
00366             TAILQ_REMOVE(app->servers, server, entries);
00367             free(server);
00368         }
00369     }
00370     
00371     if(notify) {
00372         notify_application_delete(current_svc_set->svc_set_name,
00373             app->application_name);
00374     }
00375     
00376     free(*application);
00377     *application = NULL;
00378 }
00379 
00380 
00391 static void
00392 delete_service_set(eq_serviceset_t ** service_set, boolean notify)
00393 {
00394     eq_serviceset_t * ss = *service_set;
00395     eq_app_t * app;
00396     junos_kcom_pub_ssrb_t * ssrb;
00397     
00398     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00399     
00400     // Remove service set from patricia tree
00401     if (!patricia_delete(&services_conf, &ss->node)) {
00402         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF,
00403                 "%s: Deleting service set failed", __func__);
00404         return;
00405     }
00406     
00407     if(ss->applications != NULL) {
00408         while(NULL != (app = 
00409             app_entry(patricia_find_next(ss->applications, NULL)))) {
00410             
00411             delete_application(ss->applications, &app, FALSE);
00412         }
00413         patricia_root_delete(ss->applications);
00414     }
00415     
00416     if(notify) {
00417         if(ss->svc_set_id != -1) {
00418             // ssrb was deleted already
00419             notify_serviceset_delete(ss->svc_set_name,(uint16_t)ss->svc_set_id);
00420         } else if((ssrb = get_ssrb_by_name(ss->svc_set_name)) != NULL){
00421             // ssrb was not yet deleted
00422             notify_serviceset_delete(ss->svc_set_name, ssrb->svc_set_id);
00423         } else {
00424             // can't find the service set id
00425             junos_trace(EQUILIBRIUM_TRACEFLAG_CONF,
00426                     "%s: Cannot find the service-set id to delete "
00427                     "the %s service set", __func__, ss->svc_set_name);
00428         }
00429     }
00430     
00431     free(*service_set);
00432     *service_set = NULL;
00433 }
00434 
00435 
00439 static void
00440 delete_all_servers(void)
00441 {
00442     // NOTE use current_app as context
00443 
00444     eq_server_t * server = NULL;
00445     
00446     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00447     
00448     if(current_app->servers != NULL) {
00449         while((server = TAILQ_FIRST(current_app->servers)) != NULL) {
00450             TAILQ_REMOVE(current_app->servers, server, entries);
00451             free(server);
00452         }
00453         notify_delete_all_servers(current_svc_set->svc_set_name,
00454                 current_app->application_name);
00455     }
00456 }
00457 
00458 
00462 static void
00463 delete_all_applications(void)
00464 {
00465     // NOTE use current_svc_set as context
00466     eq_app_t * app;
00467     junos_kcom_pub_ssrb_t * ssrb;
00468     
00469     INSIST_ERR(current_svc_set != NULL);
00470     
00471     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00472     
00473     if(current_svc_set->applications != NULL) {
00474         while((app = app_entry(patricia_find_next(
00475                         current_svc_set->applications, NULL))) != NULL) {
00476             delete_application(current_svc_set->applications, &app, FALSE);
00477         }
00478         patricia_root_delete(current_svc_set->applications);
00479         current_svc_set->applications = NULL;
00480         
00481         if(current_svc_set->svc_set_id != -1) {
00482             // ssrb was deleted already
00483             notify_delete_all_applications(current_svc_set->svc_set_name,
00484                     current_svc_set->svc_set_id);            
00485         } else if((ssrb = get_ssrb_by_name(current_svc_set->svc_set_name))
00486                         != NULL) {
00487             // ssrb was not yet deleted
00488             notify_delete_all_applications(current_svc_set->svc_set_name,
00489                     ssrb->svc_set_id);
00490         } else {
00491             // can't find the service set id
00492             junos_trace(EQUILIBRIUM_TRACEFLAG_CONF,
00493                     "%s: Cannot find the service-set id to delete "
00494                     "the %s service set's applications", __func__,
00495                     current_svc_set->svc_set_name);
00496         }
00497     }
00498 }
00499 
00500 
00504 static void
00505 delete_all_service_sets(void)
00506 {
00507     eq_serviceset_t * ss;
00508     
00509     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00510     
00511     while((ss = service_entry(patricia_find_next(&services_conf, NULL)))
00512             != NULL) {
00513         delete_service_set(&ss, FALSE);
00514     }
00515     
00516     notify_delete_all();
00517 }
00518 
00519 
00538 static int 
00539 parse_server(dax_walk_data_t * dwd,
00540              ddl_handle_t * dop,
00541              int action,
00542              void * data)
00543 {
00544     // NOTE use current_svc_set and current_app as context
00545     char ip_str[INET_ADDRSTRLEN];
00546     struct in_addr tmp;
00547     in_addr_t server_addr;
00548     int addr_fam;
00549     int check = *((int *)data);
00550     
00551     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00552     
00553     if(action == DAX_ITEM_DELETE_ALL) {
00554         // All servers were deleted
00555         delete_all_servers();
00556         return DAX_WALK_OK;
00557     }
00558     
00559     INSIST(dop != NULL);
00560     
00561     switch(action) {
00562 
00563     case DAX_ITEM_DELETE:
00564         // a server was deleted
00565         
00566         // get the (deleted) server adderss
00567         // for deleted items we can only get a string form:
00568         if (!dax_get_stringr_by_dwd_ident(dwd, NULL, 0,
00569                 ip_str, sizeof(ip_str))) {
00570             dax_error(dop, "Failed to parse server IP");
00571             return DAX_WALK_ABORT;
00572         }
00573         
00574         if(inet_aton(ip_str, &tmp) != 1) { // if failed
00575             dax_error(dop, "Failed to parse server IP: %s", ip_str);
00576             return DAX_WALK_ABORT;
00577         }
00578         server_addr = tmp.s_addr;
00579         
00580         if(!check) {
00581             delete_server(server_addr);
00582             
00583             // check if any servers left, o/w delete list/set
00584             if(TAILQ_FIRST(current_app->servers) == NULL) {
00585                 free(current_app);
00586                 current_app->servers = NULL;
00587             }
00588         }
00589         
00590         break;
00591         
00592     case DAX_ITEM_CHANGED:
00593         // a server was added
00594 
00595         if(!dax_get_ipaddr_by_name(dop, DDLNAME_APP_SERVERS_SERVER,
00596                 &addr_fam, &server_addr, sizeof(server_addr)) ||
00597                 addr_fam != AF_INET) {
00598             dax_error(dop, "Failed to parse server IP");
00599             return DAX_WALK_ABORT;
00600         }
00601         
00602         if(!check) {
00603             update_server(server_addr);
00604         }
00605         
00606         break;
00607         
00608     case DAX_ITEM_UNCHANGED:
00609         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, 
00610                 "%s: DAX_ITEM_UNCHANGED observed", __func__);
00611         break;
00612     
00613     default:
00614         break;
00615     }
00616 
00617     return DAX_WALK_OK;
00618 }
00619 
00620 
00642 static int 
00643 check_applications(dax_walk_data_t * dwd __unused,
00644                    ddl_handle_t * dop,
00645                    int action __unused,
00646                    void * data)
00647 {
00648     // NOTE use current_svc_set as context
00649 
00650     eq_app_key_set_t * app_key_set  = (eq_app_key_set_t *)data;
00651     eq_app_key_t * key, * tmp;
00652     int addr_fam;
00653     
00654     INSIST_ERR(dop != NULL);
00655     INSIST_ERR(app_key_set != NULL);
00656     
00657     key = calloc(1, sizeof(eq_app_key_t));
00658     INSIST_ERR(key != NULL);
00659         
00660     // read in the attributes of the address and port into the new app key
00661     if (!dax_get_ipaddr_by_name(dop,
00662             DDLNAME_SVCS_SVC_SET_EXT_SERVICE_APP_APPLICATION_ADDRESS,
00663             &addr_fam, &key->addr, sizeof(key->addr)) ||
00664             addr_fam != AF_INET) {
00665         dax_error(dop, "Failed to parse application address");
00666         return DAX_WALK_ABORT;
00667     }
00668     
00669     if (!dax_get_ushort_by_name(dop,
00670             DDLNAME_SVCS_SVC_SET_EXT_SERVICE_APP_APPLICATION_PORT,
00671             &key->port)) {
00672         dax_error(dop, "Failed to parse application port");
00673         return DAX_WALK_ABORT;
00674     }
00675     
00676     // ensure uniqueness before adding to this list
00677     
00678     tmp = TAILQ_FIRST(app_key_set);
00679     while(tmp != NULL) {
00680         if(tmp->addr == key->addr && tmp->port == key->port) {
00681             dax_error(dop, "Found another application with the same "
00682                     "facade address and port within the same service set. "
00683                     "This is not allowed.");
00684             return DAX_WALK_ABORT;
00685         }
00686         tmp = TAILQ_NEXT(tmp, entries);  
00687     }
00688     
00689     TAILQ_INSERT_TAIL(app_key_set, key, entries);
00690     
00691     return DAX_WALK_OK;
00692 }
00693 
00694 
00713 static int 
00714 parse_application(dax_walk_data_t * dwd,
00715                   ddl_handle_t * dop,
00716                   int action,
00717                   void * data)
00718 {
00719     // NOTE use current_svc_set as context
00720 
00721     char app_name[MAX_APP_NAME];
00722     in_addr_t app_addr;
00723     int addr_fam;
00724     uint16_t app_port;
00725     uint16_t app_session_timeout;
00726     eq_smon_t * app_s_monitor;
00727     eq_app_t * app;
00728     ddl_handle_t * smon_dop;
00729     ddl_handle_t * servers_dop;
00730     int check = *((int *)data);
00731 
00732     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00733     
00734     switch (action) {
00735     
00736     case DAX_ITEM_DELETE_ALL:
00737         
00738         // All applications were deleted
00739         delete_all_applications();
00740         return DAX_WALK_OK;
00741         
00742         break;
00743 
00744     case DAX_ITEM_DELETE:
00745         
00746         // get the (deleted) application name
00747         if (!dax_get_stringr_by_dwd_ident(dwd, NULL, 0,
00748                 app_name, sizeof(app_name))) {
00749             dax_error(dop, "Failed to parse a service set name");
00750             return DAX_WALK_ABORT;
00751         }
00752         
00753         if(check) {
00754             break; // nothing to do
00755         }
00756         
00757         app = app_entry(patricia_get(current_svc_set->applications,
00758                                     strlen(app_name) + 1, app_name));
00759         if(app != NULL) {
00760             delete_application(current_svc_set->applications, &app, TRUE);
00761         }
00762         
00763         // check if any applications left, o/w delete patroot for applications
00764         if((patricia_find_next(current_svc_set->applications, NULL)) == NULL) {
00765             patricia_root_delete(current_svc_set->applications);
00766             current_svc_set->applications = NULL;
00767         }
00768         
00769         break;
00770 
00771     case DAX_ITEM_CHANGED:
00772 
00773         INSIST_ERR(dop != NULL);
00774         
00775         // get the application name
00776         
00777         if (!dax_get_stringr_by_name(dop, 
00778                 DDLNAME_SVCS_SVC_SET_EXT_SERVICE_APP_APPLICATION_NAME,
00779                 app_name, sizeof(app_name))) {
00780             dax_error(dop, "Failed to parse application name");
00781             return DAX_WALK_ABORT;
00782         }
00783         
00784         // read in some of the attributes
00785         
00786         if (!dax_get_ipaddr_by_name(dop,
00787                 DDLNAME_SVCS_SVC_SET_EXT_SERVICE_APP_APPLICATION_ADDRESS,
00788                 &addr_fam, &app_addr, sizeof(app_addr)) ||
00789                 addr_fam != AF_INET) {
00790             dax_error(dop, "Failed to parse application address");
00791             return DAX_WALK_ABORT;
00792         }
00793         
00794         if (!dax_get_ushort_by_name(dop,
00795                 DDLNAME_SVCS_SVC_SET_EXT_SERVICE_APP_APPLICATION_PORT,
00796                 &app_port)) {
00797             dax_error(dop, "Failed to parse application port");
00798             return DAX_WALK_ABORT;
00799         }
00800         
00801         if (!dax_get_ushort_by_name(dop,
00802                 DDLNAME_SVCS_SVC_SET_EXT_SERVICE_APP_SESSION_TIMEOUT,
00803                 &app_session_timeout)) {
00804             dax_error(dop, "Failed to parse session timeout");
00805             return DAX_WALK_ABORT;
00806         }
00807         
00808         if(!dax_get_object_by_name(dop, DDLNAME_APP_SMON, &smon_dop, FALSE)) {
00809             app_s_monitor = NULL;
00810         } else {
00811             app_s_monitor = malloc(sizeof(eq_smon_t));
00812             INSIST(app_s_monitor != NULL);
00813             
00814             if (!dax_get_ushort_by_name(smon_dop,
00815                     DDLNAME_APP_SMON_SERVER_CONNECTION_INTERVAL,
00816                     &app_s_monitor->connection_interval)) {
00817                 dax_error(smon_dop, "Failed to parse connection interval");
00818                 dax_release_object(&smon_dop);
00819                 return DAX_WALK_ABORT;
00820             }
00821             
00822             if (!dax_get_ushort_by_name(smon_dop,
00823                     DDLNAME_APP_SMON_SERVER_CONNECTION_TIMEOUT,
00824                     &app_s_monitor->connection_timeout)) {
00825                 dax_error(smon_dop, "Failed to parse connection timeout");
00826                 dax_release_object(&smon_dop);
00827                 return DAX_WALK_ABORT;
00828             }
00829             
00830             if (!dax_get_ubyte_by_name(smon_dop,
00831                     DDLNAME_APP_SMON_SERVER_TIMEOUTS_ALLOWED,
00832                     &app_s_monitor->timeouts_allowed)) {
00833                 dax_error(smon_dop, "Failed to parse timeouts allowed");
00834                 dax_release_object(&smon_dop);
00835                 return DAX_WALK_ABORT;
00836             }
00837             
00838             if (!dax_get_ushort_by_name(smon_dop,
00839                     DDLNAME_APP_SMON_SERVER_DOWN_RETRY_INTERVAL,
00840                     &app_s_monitor->down_retry_interval)) {
00841                 dax_error(smon_dop, "Failed to parse down retry interval");
00842                 dax_release_object(&smon_dop);
00843                 return DAX_WALK_ABORT;
00844             }
00845             dax_release_object(&smon_dop);
00846             
00847             if(check) {
00848                 free(app_s_monitor);
00849             }
00850         }
00851         
00852         // update
00853         if(!check) {
00854             current_app = update_application(app_name, app_addr, app_port,
00855                     app_s_monitor, app_session_timeout);
00856         }
00857         
00858         // check servers
00859         if(!dax_get_object_by_name(dop, DDLNAME_APP_SERVERS, &servers_dop, 
00860                 FALSE)) {
00861             dax_error(dop, "Failed to parse servers");
00862             return DAX_WALK_ABORT;
00863             
00864         } else if(dax_walk_list(servers_dop, DAX_WALK_DELTA, parse_server, data)
00865                     != DAX_WALK_OK) {
00866 
00867                 dax_release_object(&servers_dop);
00868                 current_app = NULL;
00869                 return DAX_WALK_ABORT; 
00870         }
00871         current_app = NULL;
00872         dax_release_object(&servers_dop);
00873         
00874         break;
00875         
00876     case DAX_ITEM_UNCHANGED:
00877         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, 
00878                 "%s: DAX_ITEM_UNCHANGED observed", __func__);
00879         break;
00880 
00881     default:
00882         break;
00883     }
00884 
00885     return DAX_WALK_OK;
00886 }
00887 
00888 
00907 static int 
00908 parse_service_set(dax_walk_data_t * dwd,
00909                   ddl_handle_t * dop,
00910                   int action,
00911                   void * data)
00912 {
00913     const char * service_config[] = 
00914         {DDLNAME_SVCS_SVC_SET_EXT_SERVICE, NULL};
00915     const char * applications_config[] = 
00916         {DDLNAME_SVCS_SVC_SET_EXT_SERVICE_APP, NULL};
00917     const char * service_int_config[] = 
00918         {DDLNAME_INTERFACE_SERVICE, NULL};
00919 
00920     char svc_set_name[MAX_SVC_SET_NAME];
00921     char service_name[MAX_SVC_NAME];
00922     char service_int_name[MAX_SVC_INT_NAME];
00923     eq_serviceset_t * service_set = NULL;
00924     eq_app_key_set_t app_key_set;
00925     eq_app_key_t * key;
00926     ddl_handle_t * service_container_dop = NULL;
00927     ddl_handle_t * service_dop = NULL;
00928     ddl_handle_t * applications_dop = NULL;
00929     ddl_handle_t * svc_int_dop = NULL;
00930     int check = *((int *)data);
00931     int found = 0;
00932 
00933     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s", __func__);
00934     
00935     switch (action) {
00936 
00937     case DAX_ITEM_DELETE_ALL:
00938 
00939         // All items under service-set were deleted
00940         delete_all_service_sets();
00941         return DAX_WALK_OK;
00942         
00943         break;
00944     
00945     case DAX_ITEM_DELETE:
00946         
00947         // One item got deleted
00948         
00949         // get the (deleted) service set name
00950         if (!dax_get_stringr_by_dwd_ident(dwd, NULL, 0,
00951                 svc_set_name, sizeof(svc_set_name))) {
00952             dax_error(dop, "Failed to parse a service set name");
00953             return DAX_WALK_ABORT;
00954         }
00955         
00956         if(!check) {
00957             // check if we know about this one
00958             service_set = service_entry(patricia_get(&services_conf,
00959                                         strlen(svc_set_name) + 1, svc_set_name));
00960             
00961             if(service_set != NULL) {
00962                 // add a delete action to action list &
00963                 // remove service-set from config
00964                 delete_service_set(&service_set, TRUE);
00965             }
00966         }
00967         
00968         break;
00969 
00970     case DAX_ITEM_CHANGED:
00971         
00972         // service set added or renamed
00973         // everything under it will be marked changed too
00974 
00975         INSIST_ERR(dop != NULL);
00976         
00977         // get the service set name
00978         if (!dax_get_stringr_by_name(dop, DDLNAME_SERVICE_SET_IDENT,
00979                 svc_set_name, sizeof(svc_set_name))) {
00980             dax_error(dop, "Failed to parse a service set name");
00981             return DAX_WALK_ABORT;
00982         }
00983         
00984         // check for our service in the service-set
00985         // i.e. extension-service with "equilibrium-" prefixed service-name
00986         
00987         if (dax_get_object_by_path(dop, service_config,
00988                 &service_container_dop, FALSE)) {
00989         
00990             // some extension-service config exists
00991             // see if it is an equilibrium service
00992             
00993             while (dax_visit_container(service_container_dop, &service_dop)) {
00994                 
00995                 if (!dax_get_stringr_by_name(service_dop,
00996                         DDLNAME_EXTENTION_SERVICE_IDENT, service_name, 
00997                         sizeof(service_name))) {
00998                     dax_error(service_dop,
00999                             "Failed to parse an extension-service name");
01000                     return DAX_WALK_ABORT;
01001                 }
01002                 
01003                 // check chosen service name for prefix:
01004                 if(strstr(service_name, equilibrium_service_prefix) == NULL) {
01005                     continue;
01006                 }
01007                 
01008                 // found equilibrium service!
01009                 
01010                 if(found) { // already found...error (caught in check)
01011                     dax_error(service_dop, "More than one equilibrium "
01012                         "service per service set is not allowed");
01013                     dax_release_object(&service_dop);
01014                     dax_release_object(&service_container_dop);
01015                     return DAX_WALK_ABORT;
01016                 }
01017                 found = 1;
01018                 
01019                 // get changes in the service-set's info
01020                 
01021                 // update service interface info
01022                 if(!dax_get_object_by_path(dop, service_int_config,
01023                         &svc_int_dop, FALSE)) {
01024                     
01025                     dax_error(service_dop, "Equilibrium service has no "
01026                             "service interface configured in service set");
01027                     dax_release_object(&service_dop);
01028                     dax_release_object(&service_container_dop);
01029                     return DAX_WALK_ABORT;
01030                 }
01031                 
01032                 // get service-int name
01033                 if (!dax_get_stringr_by_name(svc_int_dop,
01034                         DDLNAME_INTERFACE_SERVICE_SVC_INT,
01035                         service_int_name, sizeof(service_int_name))) {
01036                     
01037                     dax_error(svc_int_dop,
01038                             "Failed to parse the service-interface name");
01039                     dax_release_object(&service_dop);
01040                     dax_release_object(&svc_int_dop);
01041                     dax_release_object(&service_container_dop);
01042                     return DAX_WALK_ABORT;
01043                 }
01044                 
01045                 dax_release_object(&svc_int_dop);
01046                 
01047                 // update service set's info
01048                 if(!check) {
01049                     current_svc_set = update_service_set(
01050                             svc_set_name, service_name, service_int_name);
01051                 }
01052                 
01053                 // check applications
01054                 if(!dax_get_object_by_path(service_dop, applications_config,
01055                         &applications_dop, FALSE)) {
01056                     
01057                     dax_error(service_dop, "Equilibrium "
01058                         "service has no applications configured");
01059                     dax_release_object(&service_dop);
01060                     dax_release_object(&service_container_dop);
01061                     return DAX_WALK_ABORT;
01062                 }
01063                 
01064                 if(dax_walk_list(applications_dop, DAX_WALK_DELTA, 
01065                         parse_application, data) != DAX_WALK_OK) {
01066                     
01067                     dax_release_object(&service_dop);
01068                     dax_release_object(&service_container_dop);
01069                     current_svc_set = NULL;
01070                     return DAX_WALK_ABORT; 
01071                 }
01072                 if(check) {
01073                     // check that address and port combination is unique 
01074                     // within the service set
01075                     
01076                     TAILQ_INIT(&app_key_set);
01077                     
01078                     if(dax_walk_list(applications_dop, DAX_WALK_CONFIGURED, 
01079                             check_applications, &app_key_set) != DAX_WALK_OK) {
01080                         
01081                         dax_release_object(&service_dop);
01082                         dax_release_object(&service_container_dop);
01083                         current_svc_set = NULL;
01084                         // empty the set
01085                         while((key = TAILQ_FIRST(&app_key_set)) != NULL) {
01086                             TAILQ_REMOVE(&app_key_set, key, entries);  
01087                             free(key);
01088                         }
01089                         return DAX_WALK_ABORT; 
01090                     }
01091                     
01092                     // empty the set
01093                     while((key = TAILQ_FIRST(&app_key_set)) != NULL) {
01094                         TAILQ_REMOVE(&app_key_set, key, entries);  
01095                         free(key);
01096                     }
01097                 }
01098                 current_svc_set = NULL;
01099                 
01100             } // end while
01101             dax_release_object(&service_container_dop);
01102             
01103             if(found) {
01104                 return DAX_WALK_OK;
01105             }
01106             // no equilibrium service configured in service set if we reach here
01107         }
01108         
01109         if(!check) {
01110             // check if previously knew about this service-set
01111             service_set = service_entry(patricia_get(&services_conf,
01112                                        strlen(svc_set_name) + 1, svc_set_name));
01113             
01114             if(service_set != NULL) { // if so,
01115                 delete_service_set(&service_set, TRUE); // delete it
01116             }
01117         }
01118         
01119         break;
01120         
01121     case DAX_ITEM_UNCHANGED:
01122         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, 
01123                 "%s: DAX_ITEM_UNCHANGED observed", __func__);
01124         break;
01125 
01126     default:
01127         break;
01128     }
01129 
01130     return DAX_WALK_OK;
01131 }
01132 
01133 
01134 /*** GLOBAL/EXTERNAL Functions ***/
01135 
01136 
01141 void
01142 init_config(void)
01143 {
01144                         // root, is key ptr, key size, key offset
01145     patricia_root_init(&services_conf, FALSE, MAX_SVC_SET_NAME, 0);
01146     patricia_root_init(&ssrb_conf, FALSE, MAX_SVC_SET_NAME, 0);
01147 }
01148 
01149 
01153 void
01154 clear_config(void)
01155 {
01156     delete_all_service_sets();
01157     
01158     clear_ssrb_config();
01159 }
01160 
01161 
01165 void
01166 clear_ssrb_config(void)
01167 {
01168     eq_ssrb_t * s;
01169     while((s = ssrb_entry(patricia_find_next(&ssrb_conf, NULL))) != NULL) {
01170         if(!patricia_delete(&ssrb_conf, &s->node)) {
01171             LOG(TRACE_LOG_ERR, "%s: patricia delete FAILED!",
01172                 __func__);
01173         }
01174         free(s);
01175     }
01176 }
01177 
01178 
01188 int
01189 add_ssrb(junos_kcom_pub_ssrb_t * ssrb)
01190 {
01191     eq_ssrb_t * s;
01192     
01193     // check for existance
01194     if(get_ssrb_by_name(ssrb->svc_set_name) != NULL)
01195         return EFAIL;
01196     
01197     // create data struct
01198     s = malloc(sizeof(eq_ssrb_t));
01199     INSIST(s != NULL);
01200     
01201     // copy data into new struct with node, init node, and add to tree
01202     strncpy(s->ssrb.svc_set_name, ssrb->svc_set_name, MAX_SVC_SET_NAME); 
01203     s->ssrb.svc_set_id = ssrb->svc_set_id;
01204     s->ssrb.in_nh_idx = ssrb->in_nh_idx;
01205     s->ssrb.out_nh_idx = ssrb->out_nh_idx;
01206     
01207     patricia_node_init_length(&s->node, strlen(ssrb->svc_set_name) +1);
01208     if(!patricia_add(&ssrb_conf, &s->node)) {
01209         LOG(TRACE_LOG_ERR, "%s: failed to add SSRB to configuration",
01210                 __func__);
01211         return EFAIL;
01212     }
01213     return SUCCESS;
01214     
01215 }
01216 
01217 
01227 junos_kcom_pub_ssrb_t *
01228 get_ssrb_by_name(char * name)
01229 {
01230     eq_ssrb_t * s;
01231     
01232     s = ssrb_entry(patricia_get(&ssrb_conf, strlen(name) + 1, name));
01233     if(s != NULL)
01234         return &s->ssrb;
01235     return NULL;
01236 }
01237 
01238 
01248 junos_kcom_pub_ssrb_t *
01249 get_ssrb_by_id(uint16_t svc_set_id)
01250 {
01251     eq_ssrb_t * s;
01252     
01253     s = ssrb_entry(patricia_find_next(&ssrb_conf, NULL));
01254     while(s != NULL) {
01255         if(s->ssrb.svc_set_id == svc_set_id) {
01256             return &s->ssrb;
01257         }
01258         s = ssrb_entry(patricia_find_next(&ssrb_conf, &s->node));
01259     }
01260     return NULL;
01261 }
01262 
01263 
01270 void
01271 delete_ssrb_by_name(char * name)
01272 {
01273     eq_ssrb_t * s;
01274     eq_serviceset_t * service_set;
01275     
01276     if(name == NULL)
01277         return;
01278     
01279     s = ssrb_entry(patricia_get(&ssrb_conf, strlen(name) + 1, name));
01280     
01281     if(s == NULL)
01282         return;
01283     
01284     /*
01285      * We are deleting the SSRB (and namely the service-set ID), so it 
01286      * won't be available for lookup later. If the service set is still 
01287      * configured at this time, that means it will get deleted later, but the 
01288      * SSRB delete came first. So we store the id in the configured service-set
01289      * so that it is available there later upon the delete at
01290      * configuration-read time.
01291      */
01292 
01293     // check if this service-set is still configured
01294     
01295     service_set = service_entry(patricia_get(&services_conf,
01296                                         strlen(name) + 1, name));
01297     if(service_set != NULL) {
01298         service_set->svc_set_id = s->ssrb.svc_set_id;
01299     }
01300     
01301     /* remove data from patricia tree */
01302     if (!patricia_delete(&ssrb_conf, &s->node)) {
01303         LOG(TRACE_LOG_ERR, "%s: patricia delete FAILED!",
01304             __func__);
01305     }
01306     free(s);
01307 }
01308 
01309 
01316 void
01317 delete_ssrb_by_id(uint16_t svc_set_id)
01318 {
01319     delete_ssrb_by_name((get_ssrb_by_id(svc_set_id))->svc_set_name);
01320 }
01321 
01322 
01338 void
01339 set_server_status(uint16_t svc_set_id,
01340                   char * app_name,
01341                   in_addr_t server_addr,
01342                   uint8_t status)
01343 {
01344     junos_kcom_pub_ssrb_t * ssrb;
01345     eq_serviceset_t * service_set = NULL;
01346     eq_app_t * app = NULL;
01347     eq_server_t * server = NULL;
01348     
01349     INSIST_ERR(app_name != NULL);
01350     
01351     // get service set name
01352     if((ssrb = get_ssrb_by_id(svc_set_id)) == NULL) {
01353         return;
01354     }
01355     
01356     // get service set
01357     service_set = service_entry(patricia_get(&services_conf,
01358                     strlen(ssrb->svc_set_name) + 1, ssrb->svc_set_name));
01359     
01360     if(service_set == NULL || service_set->applications == NULL) { 
01361         return;
01362     }
01363     
01364     // get application
01365     app = app_entry(patricia_get(service_set->applications,
01366             strlen(app_name) + 1, app_name));
01367     
01368     if(app == NULL || app->servers == NULL) { 
01369         return;
01370     }
01371     
01372     // find matching server
01373     server = TAILQ_FIRST(app->servers);
01374     while(server != NULL) {
01375         if(server->server_addr == server_addr) {
01376             server->status = status; // update status
01377             return;
01378         }
01379         server = TAILQ_NEXT(server, entries);
01380     }
01381     // if here, no matching server was found
01382 }
01383 
01384 
01397 void
01398 set_app_sessions(uint16_t svc_set_id,
01399                  char * app_name,
01400                  uint32_t session_count)
01401 {
01402     junos_kcom_pub_ssrb_t * ssrb;
01403     eq_serviceset_t * service_set = NULL;
01404     eq_app_t * app = NULL;
01405     
01406     INSIST_ERR(app_name != NULL);
01407     
01408     // get service set name
01409     if((ssrb = get_ssrb_by_id(svc_set_id)) == NULL) {
01410         return;
01411     }
01412     
01413     // get service set
01414     service_set = service_entry(patricia_get(&services_conf,
01415                     strlen(ssrb->svc_set_name) + 1, ssrb->svc_set_name));
01416     
01417     if(service_set == NULL || service_set->applications == NULL) { 
01418         return;
01419     }
01420     
01421     // get application
01422     app = app_entry(patricia_get(service_set->applications,
01423             strlen(app_name) + 1, app_name));
01424     
01425     if(app == NULL) { 
01426         return; // if here, no matching app was found
01427     }
01428     
01429     app->session_count = session_count;
01430 }
01431 
01432 
01442 eq_serviceset_t *
01443 next_service_set(eq_serviceset_t * data)
01444 {
01445     return service_entry(
01446             patricia_find_next(&services_conf, (data ? &(data->node) : NULL)));
01447 }
01448 
01449 
01462 eq_app_t *
01463 next_application(eq_serviceset_t * ss, eq_app_t * data)
01464 {
01465     return app_entry(patricia_find_next(ss->applications,
01466                                     (data ? &(data->node) : NULL)));
01467 }
01468 
01469 
01478 eq_serviceset_t *
01479 find_service_set(const char * name)
01480 {
01481     return service_entry(patricia_get(&services_conf, strlen(name) + 1, name));
01482 }
01483 
01484 
01496 eq_app_t *
01497 find_application(const eq_serviceset_t * ss, const char * name)
01498 {
01499     return app_entry(patricia_get(ss->applications, strlen(name) + 1, name));
01500 }
01501 
01502 
01514 int
01515 equilibrium_config_read(int check)
01516 {
01517     const char * services_config[] = {DDLNAME_SVCS, DDLNAME_SVCS_SVC_SET, NULL};
01518     
01519     ddl_handle_t * top = NULL;
01520 
01521     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s: Starting equilibrium "
01522             "configuration load", __func__);
01523     
01524     // Load the rest of the configuration under services service-set
01525     
01526     if (!dax_get_object_by_path(NULL, services_config, &top, FALSE))  {
01527 
01528         // service-set config does not exist
01529         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, 
01530                 "%s: Cleared equilibrium services configuration", __func__);
01531 
01532         delete_all_service_sets();
01533         return SUCCESS;
01534     }
01535     if (!dax_is_changed(top)) { // if not changed
01536         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s: No change in equilibrium"
01537             " services configuration", __func__);
01538         return SUCCESS;
01539     }
01540 
01541     // services configuration has changed
01542     
01543     if(dax_walk_list(top, DAX_WALK_DELTA, parse_service_set, &check)
01544             != DAX_WALK_OK) {
01545         dax_release_object(&top);
01546         junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, "%s: walk service list failed"
01547             " services configuration", __func__);
01548         return EFAIL;
01549     }
01550     
01551     if(!check) {
01552         process_notifications();
01553     }
01554     
01555     junos_trace(EQUILIBRIUM_TRACEFLAG_CONF, 
01556             "%s: Loaded equilibrium configuration", __func__);
01557 
01558     return SUCCESS;
01559 }

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:57 2010 for SDK Your Net Corporation Equilibrium Load Balancer Example: equilibrium-mgmt 1.0 by Doxygen 1.5.1