Browse Source

Merge branch 'trac2947_2'

Mukund Sivaraman 12 years ago
parent
commit
9a3ddf1e2b

+ 0 - 9
src/bin/cfgmgr/plugins/tests/datasrc_test.py

@@ -96,15 +96,6 @@ class DatasrcTest(unittest.TestCase):
             "params": {}
         }]})
 
-    def test_dstype_bad(self):
-        """
-        The configuration is correct by the spec, but it would be rejected
-        by the client list. Check we reject it.
-        """
-        self.reject({"IN": [{
-            "type": "No such type"
-        }]})
-
     def test_invalid_mem_params(self):
         """
         The client list skips in-memory sources. So we check it locally that

+ 14 - 6
src/lib/datasrc/client_list.cc

@@ -110,12 +110,20 @@ ConfigurableClientList::configure(const ConstElementPtr& config,
                           << datasrc_name);
             }
 
-            // Create a client for the underling data source via factory.
-            // If it's our internal type of data source, this is essentially
-            // no-op.  In the latter case, it's of no use unless cache is
-            // allowed; we simply skip building it in that case.
-            const DataSourcePair dsrc_pair = getDataSourceClient(type,
-                                                                 param_conf);
+            DataSourcePair dsrc_pair;
+            try {
+                // Create a client for the underling data source via
+                // factory.  If it's our internal type of data source,
+                // this is essentially no-op.  In the latter case, it's
+                // of no use unless cache is allowed; we simply skip
+                // building it in that case.
+                dsrc_pair = getDataSourceClient(type, param_conf);
+            } catch (const DataSourceLibraryError& ex) {
+                LOG_ERROR(logger, DATASRC_LIBRARY_ERROR).
+                    arg(datasrc_name).arg(rrclass_).arg(ex.what());
+                continue;
+            }
+
             if (!allow_cache && !dsrc_pair.first) {
                 LOG_WARN(logger, DATASRC_LIST_NOT_CACHED).
                     arg(datasrc_name).arg(rrclass_);

+ 5 - 0
src/lib/datasrc/datasrc_messages.mes

@@ -370,6 +370,11 @@ Therefore, the entire data source will not be available for this process. If
 this is a problem, you should configure the zones of that data source to some
 database backend (sqlite3, for example) and use it from there.
 
+% DATASRC_LIBRARY_ERROR failure loading %1 datasource library for class %2: %3
+There was a problem loading the dynamic library for a data source. This
+backend is hence not available, and any data sources that use this
+backend will not be available.
+
 % DATASRC_LOAD_ZONE_ERROR Error loading zone %1/%2 on data source '%3': %4
 During data source configuration, an error was found in the zone data
 when it was being loaded in to memory on the shown data source.  This

+ 2 - 2
src/lib/datasrc/factory.cc

@@ -83,8 +83,8 @@ LibraryContainer::LibraryContainer(const std::string& name) {
     if (ds_lib_ == NULL) {
         // This may cause the filename to appear twice in the actual
         // error, but the output of dlerror is implementation-dependent
-        isc_throw(DataSourceLibraryError, "dlopen failed for " << name << 
-                                          ": " << dlerror());
+        isc_throw(DataSourceLibraryOpenError,
+                  "dlopen failed for " << name << ": " << dlerror());
     }
 }
 

+ 12 - 3
src/lib/datasrc/factory.h

@@ -27,7 +27,7 @@ namespace isc {
 namespace datasrc {
 
 
-/// \brief Raised if there is an error loading the datasource implementation
+/// \brief Raised if there is an error in the datasource implementation
 ///        library
 class DataSourceLibraryError : public DataSourceError {
 public:
@@ -35,13 +35,22 @@ public:
         DataSourceError(file, line, what) {}
 };
 
+/// \brief Raised if there is an error opening the the datasource
+///        implementation library
+class DataSourceLibraryOpenError : public DataSourceLibraryError {
+public:
+    DataSourceLibraryOpenError(const char* file, size_t line,
+                               const char* what) :
+        DataSourceLibraryError(file, line, what) {}
+};
+
 /// \brief Raised if there is an error reading a symbol from the datasource
 ///        implementation library
-class DataSourceLibrarySymbolError : public DataSourceError {
+class DataSourceLibrarySymbolError : public DataSourceLibraryError {
 public:
     DataSourceLibrarySymbolError(const char* file, size_t line,
                                  const char* what) :
-        DataSourceError(file, line, what) {}
+        DataSourceLibraryError(file, line, what) {}
 };
 
 typedef DataSourceClient* ds_creator(isc::data::ConstElementPtr config,

+ 34 - 0
src/lib/datasrc/tests/client_list_unittest.cc

@@ -16,6 +16,7 @@
 
 #include <datasrc/client_list.h>
 #include <datasrc/client.h>
+#include <datasrc/factory.h>
 #include <datasrc/cache_config.h>
 #include <datasrc/zone_iterator.h>
 #include <datasrc/exceptions.h>
@@ -71,6 +72,10 @@ public:
         if (type == "error") {
             isc_throw(DataSourceError, "The error data source type");
         }
+        if (type == "library_error") {
+            isc_throw(DataSourceLibraryError,
+                      "The library error data source type");
+        }
         if (type == "MasterFiles") {
             return (DataSourcePair(0, DataSourceClientContainerPtr()));
         }
@@ -705,6 +710,35 @@ TEST_P(ListTest, dataSrcError) {
     checkDS(0, "test_type", "{}", false);
 }
 
+// In case of library errors, the rest of the data sources should be
+// unaffected.
+TEST_P(ListTest, dataSrcLibraryError) {
+    EXPECT_EQ(0, list_->getDataSources().size());
+    const ConstElementPtr elem(Element::fromJSON("["
+        "{"
+        "   \"type\": \"type1\","
+        "   \"cache-enable\": false,"
+        "   \"params\": {}"
+        "},"
+        "{"
+        "   \"type\": \"library_error\","
+        "   \"cache-enable\": false,"
+        "   \"params\": {}"
+        "},"
+        "{"
+        "   \"type\": \"type2\","
+        "   \"cache-enable\": false,"
+        "   \"params\": {}"
+        "}]"
+    ));
+    list_->configure(elem, true);
+    EXPECT_EQ(2, list_->getDataSources().size());
+    checkDS(0, "type1", "{}", false);
+    checkDS(1, "type2", "{}", false);
+    // Check the exact configuration is preserved
+    EXPECT_EQ(elem, list_->getConfiguration());
+}
+
 // Check we can get the cache
 TEST_P(ListTest, configureCacheEmpty) {
     const ConstElementPtr elem(Element::fromJSON("["

+ 0 - 3
src/lib/python/isc/datasrc/tests/clientlist_test.py

@@ -102,9 +102,6 @@ class ClientListTest(unittest.TestCase):
         self.assertRaises(isc.datasrc.Error, self.clist.configure,
                           '"bad type"', True)
         self.assertRaises(isc.datasrc.Error, self.clist.configure, '''[{
-            "type": "bad type"
-        }]''', True)
-        self.assertRaises(isc.datasrc.Error, self.clist.configure, '''[{
             bad JSON,
         }]''', True)
         self.assertRaises(TypeError, self.clist.configure, [], True)

+ 6 - 0
tests/lettuce/configurations/example.org.inmem.config

@@ -22,6 +22,12 @@
                     "params": {
                         "example.org": "data/example.org"
                     }
+                },
+                {
+                    "type": "broken_libraries_should_be_skipped",
+                    "cache-enable": false,
+                    "params": {
+                    }
                 }
             ]
         }

+ 1 - 0
tests/lettuce/features/queries.feature

@@ -53,6 +53,7 @@ Feature: Querying feature
         And wait for bind10 stderr message BIND10_STARTED_CC
         And wait for bind10 stderr message CMDCTL_STARTED
         And wait for bind10 stderr message AUTH_SERVER_STARTED
+        And wait for bind10 stderr message DATASRC_LIBRARY_ERROR
         And wait for bind10 stderr message STATS_STARTING
 
         bind10 module Auth should be running