Back to index

nordugrid-arc-nox  1.1.0~rc6
BootstrapISIS.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <time.h>
00006 #include <unistd.h>
00007 #include <algorithm>
00008 
00009 #include <arc/URL.h>
00010 #include <arc/XMLNode.h>
00011 #include <arc/message/PayloadSOAP.h>
00012 #include <arc/client/ClientInterface.h>
00013 #include <arc/StringConv.h>
00014 #include "InfoRegister.h"
00015 #ifdef WIN32
00016 #include <arc/win32.h>
00017 #endif
00018 
00019 namespace Arc {
00020 
00021 static Logger logger_(Logger::rootLogger, "InfoSys");
00022 
00023 struct Registrar_data {
00024    ISIS_description isis;
00025    InfoRegistrar *registrar;
00026 };
00027 
00028     void InfoRegistrar::initISIS(XMLNode cfg) {
00029         logger_.msg(DEBUG, "Initialize ISIS handler");
00030         // Process configuration
00031         defaultBootstrapISIS.url   = (std::string)cfg["URL"];
00032         if(defaultBootstrapISIS.url.empty()) {
00033             logger_.msg(ERROR, "Can't recognize URL: %s",(std::string)cfg["URL"]);
00034         } else {
00035             //logger_.msg(VERBOSE, "InfoRegistrar created for URL: %s",(std::string)cfg["URL"]);
00036         }
00037         defaultBootstrapISIS.key = (std::string)cfg["KeyPath"];
00038         defaultBootstrapISIS.cert = (std::string)cfg["CertificatePath"];
00039         defaultBootstrapISIS.proxy = (std::string)cfg["ProxyPath"];
00040         defaultBootstrapISIS.cadir = (std::string)cfg["CACertificatesDir"];
00041         defaultBootstrapISIS.cafile = (std::string)cfg["CACertificatePath"];
00042                
00043         // Set up default values
00044         myISIS = defaultBootstrapISIS;
00045         originalISISCount = 1;
00046         myISISList.push_back(myISIS);
00047 
00048         //getISISList(myISIS);
00049         myISISList_initialized = false;
00050         logger_.msg(DEBUG, "Initialize ISIS handler succeeded");
00051     }
00052 
00053     void InfoRegistrar::removeISIS(ISIS_description isis) {
00054         logger_.msg(VERBOSE, "Remove ISIS (%s) from list", isis.url);
00055         // Remove isis from myISISList
00056         for (std::vector<ISIS_description>::iterator it = myISISList.begin();
00057              it < myISISList.end() && ((*it).url != myISIS.url || myISISList.erase(it) == it); it++);
00058 
00059         // If the 'isis' is the currently used (myISIS) isis
00060         if ( isis.url == myISIS.url && myISISList.size() != 0 ) {
00061             // Select a new random isis from the list
00062             std::srand(time(NULL));
00063             ISIS_description rndISIS = myISISList[std::rand() % myISISList.size()];
00064 
00065             // Add the neighbors of the newly selected ISIS to the list and set myISIS to one of them
00066             getISISList(rndISIS);
00067         }
00068 
00069         // Check if there is enough ISIS's left
00070         getISIS();
00071     }
00072 
00073     void InfoRegistrar::getISISList(ISIS_description isis) {
00074         logger_.msg(VERBOSE, "getISISList from %s", isis.url);
00075         logger_.msg(VERBOSE, "Key %s, Cert: %s, CA: %s", isis.key, isis.cert, isis.cadir);
00076         // Try to get ISISList from the actual ISIS
00077         // Compose getISISList request
00078         NS query_ns;
00079         query_ns[""] = "http://www.nordugrid.org/schemas/isis/2007/06";
00080 
00081         // Try to get ISIS.getISISList()
00082         PayloadSOAP request(query_ns);
00083         request.NewChild("GetISISList");
00084 
00085         // Send message
00086         PayloadSOAP *response;
00087         MCCConfig mcc_cfg;
00088         mcc_cfg.AddPrivateKey(isis.key);
00089         mcc_cfg.AddCertificate(isis.cert);
00090         mcc_cfg.AddProxy(isis.proxy);
00091         if (!isis.cadir.empty()) {
00092             mcc_cfg.AddCADir(isis.cadir);
00093         }
00094         if (!isis.cafile.empty()) {
00095             mcc_cfg.AddCAFile(isis.cafile);
00096         }
00097 
00098         int retry_ = retry;
00099         int reconnection = 0;
00100         while ( retry_ >= 1 ) {
00101             ClientSOAP cli(mcc_cfg,isis.url,60);
00102             MCC_Status status = cli.process(&request, &response);
00103             retry_--;
00104             reconnection++;
00105             // If the given ISIS wasn't available try reconnect
00106             if (!status.isOk() || !response || !bool((*response)["GetISISListResponse"])) {
00107                 logger_.msg(VERBOSE, "ISIS (%s) is not available or not valid response. (%d. reconnection)", isis.url, reconnection);
00108             } else {
00109                 logger_.msg(VERBOSE, "Connection to the ISIS (%s) is success and get the list of ISIS.", isis.url);
00110                 break;
00111             }
00112         }
00113 
00114         // If the given ISIS wasn't available remove it and return
00115         if ( retry_ == 0 ) {
00116             removeISIS(isis);
00117             return;
00118         }
00119 
00120         // Merge result with the orignal list of known ISIS's
00121         int i = 0;
00122         while((bool)(*response)["GetISISListResponse"]["EPR"][i]) {
00123             bool ISIS_found = false;
00124             for (std::vector<ISIS_description>::iterator it = myISISList.begin();
00125                 it < myISISList.end() && ((*it).url != (std::string) (*response)["GetISISListResponse"]["EPR"][i]
00126                 || (ISIS_found = true)); it++);
00127             if ( !ISIS_found ) {
00128                 ISIS_description new_ISIS;
00129                 new_ISIS.url = (std::string)(*response)["GetISISListResponse"]["EPR"][i];
00130                 new_ISIS.key = defaultBootstrapISIS.key;
00131                 new_ISIS.cert = defaultBootstrapISIS.cert;
00132                 new_ISIS.proxy = defaultBootstrapISIS.proxy;
00133                 new_ISIS.cadir = defaultBootstrapISIS.cadir;
00134                 new_ISIS.cafile = defaultBootstrapISIS.cafile;
00135                 myISISList.push_back(new_ISIS);
00136                 logger_.msg(VERBOSE, "GetISISList add this (%s) ISIS into the list.", new_ISIS.url);
00137             }
00138             i++;
00139         }
00140 
00141         // Update the original number of ISIS's variable
00142         originalISISCount = myISISList.size();
00143 
00144         // Select a new random isis from the list
00145         std::srand(time(NULL));
00146         ISIS_description rndISIS = myISISList[std::rand() % myISISList.size()];
00147 
00148         logger_.msg(VERBOSE, "Chosen ISIS for communication: %s", rndISIS.url);
00149         myISIS = rndISIS;
00150 
00151         if (response) delete response;
00152     }
00153 
00154     ISIS_description InfoRegistrar::getISIS(void) {
00155         logger_.msg(VERBOSE, "Get ISIS from list of ISIS handler");
00156         if (myISISList.size() == 0) {
00157             if ( myISIS.url == defaultBootstrapISIS.url ) {
00158                 logger_.msg(WARNING, "There is no more ISIS available. The list of ISIS's is already empty.");
00159 
00160                 // Set up default values for the further tries
00161                 myISIS = defaultBootstrapISIS;
00162                 originalISISCount = 1;
00163                 myISISList.push_back(myISIS);
00164 
00165                 // If there is no available, return an empty ISIS
00166                 ISIS_description temporary_ISIS;
00167                 temporary_ISIS.url = "";
00168                 return temporary_ISIS;
00169             } else {
00170                 // Try to receive the "original" bootsrap informations, if the BootstrapISIS is already available.
00171                 getISISList(defaultBootstrapISIS);
00172                 return getISIS();
00173             }
00174         }
00175         if (myISISList.size() == 1) {
00176             // If there is only one known ISIS than force the check of availability of new cloud members.
00177             getISISList(myISIS);
00178             return myISIS;
00179         }
00180         if (myISISList.size() <= originalISISCount / 2) {
00181             // Select a new random isis from the list
00182             std::srand(time(NULL));
00183             ISIS_description rndISIS = myISISList[std::rand() % myISISList.size()];
00184 
00185             // Add the neighbors of the newly selected ISIS to the list and set myISIS to one of them
00186             getISISList(rndISIS);
00187         }
00188         //And finally...
00189         return myISIS;
00190     }
00191 
00192 }
00193