Browse Source

[2436] Perform the validation in ZoneLoader

TODO: Modify this commit and use the datasource RRsetCollection. This
way it doesn't work.
Michal 'vorner' Vaner 12 years ago
parent
commit
f4e6ab2a98

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

@@ -844,3 +844,14 @@ data source.
 % DATASRC_UNEXPECTED_QUERY_STATE unexpected query state
 % DATASRC_UNEXPECTED_QUERY_STATE unexpected query state
 This indicates a programming error. An internal task of unknown type was
 This indicates a programming error. An internal task of unknown type was
 generated.
 generated.
+
+% DATASRC_VALIDATE_ERROR validation of zone %1/%2 failed: %3
+The zone was loaded into the data source successfully, but the content fails
+basic sanity checks. See the message if you want to know what exactly is wrong
+with the data. The data can not be used and previous version, if any, will be
+preserved.
+
+% DATASRC_VALIDATE_WARNING %1/%2: %3
+The zone was loaded, but there's some problem with the content. The problem
+is not serious enough to make the zone unusable, but it should still be checked
+and fixed. See the message to know what exactly is wrong with the data.

+ 8 - 6
src/lib/datasrc/tests/zone_loader_unittest.cc

@@ -82,9 +82,9 @@ public:
 // and this way, it is much simpler.
 // and this way, it is much simpler.
 class Updater : public ZoneUpdater {
 class Updater : public ZoneUpdater {
 public:
 public:
-    Updater(MockClient* client) :
+    Updater(MockClient* client, const Name& name) :
         client_(client),
         client_(client),
-        finder_(client_->rrclass_)
+        finder_(client_->rrclass_, name)
     {}
     {}
     virtual ZoneFinder& getFinder() {
     virtual ZoneFinder& getFinder() {
         return (finder_);
         return (finder_);
@@ -105,14 +105,15 @@ private:
     MockClient* client_;
     MockClient* client_;
     class Finder : public ZoneFinder {
     class Finder : public ZoneFinder {
     public:
     public:
-        Finder(const RRClass& rrclass) :
-            class_(rrclass)
+        Finder(const RRClass& rrclass, const Name& name) :
+            class_(rrclass),
+            name_(name)
         {}
         {}
         virtual RRClass getClass() const {
         virtual RRClass getClass() const {
             return (class_);
             return (class_);
         }
         }
         virtual Name getOrigin() const {
         virtual Name getOrigin() const {
-            isc_throw(isc::NotImplemented, "Method not used in tests");
+            return (name_);
         }
         }
         virtual shared_ptr<Context> find(const Name&, const RRType&,
         virtual shared_ptr<Context> find(const Name&, const RRType&,
                                          const FindOptions)
                                          const FindOptions)
@@ -130,6 +131,7 @@ private:
         }
         }
     private:
     private:
         const RRClass class_;
         const RRClass class_;
+        const Name name_;
     } finder_;
     } finder_;
 };
 };
 
 
@@ -144,7 +146,7 @@ MockClient::getUpdater(const Name& name, bool replace, bool journaling) const {
     // const_cast is bad. But the const on getUpdater seems wrong in the first
     // const_cast is bad. But the const on getUpdater seems wrong in the first
     // place, since updater will be modifying the data there. And the updater
     // place, since updater will be modifying the data there. And the updater
     // wants to store data into the client so we can examine it later.
     // wants to store data into the client so we can examine it later.
-    return (ZoneUpdaterPtr(new Updater(const_cast<MockClient*>(this))));
+    return (ZoneUpdaterPtr(new Updater(const_cast<MockClient*>(this), name)));
 }
 }
 
 
 class ZoneLoaderTest : public ::testing::Test {
 class ZoneLoaderTest : public ::testing::Test {

+ 34 - 0
src/lib/datasrc/zone_loader.cc

@@ -19,8 +19,13 @@
 #include <datasrc/data_source.h>
 #include <datasrc/data_source.h>
 #include <datasrc/iterator.h>
 #include <datasrc/iterator.h>
 #include <datasrc/zone.h>
 #include <datasrc/zone.h>
+#include <datasrc/logger.h>
+#include <datasrc/rrset_collection.h>
 
 
 #include <dns/rrset.h>
 #include <dns/rrset.h>
+#include <dns/zone_checker.h>
+
+#include <boost/bind.hpp>
 
 
 using isc::dns::Name;
 using isc::dns::Name;
 using isc::dns::ConstRRsetPtr;
 using isc::dns::ConstRRsetPtr;
@@ -99,6 +104,22 @@ copyRRsets(const ZoneUpdaterPtr& destination, const ZoneIteratorPtr& source,
     return (false); // Not yet, there may be more
     return (false); // Not yet, there may be more
 }
 }
 
 
+void
+logWarning(const dns::Name* zone_name, const dns::RRClass* rrclass,
+           const std::string& reason)
+{
+    LOG_WARN(logger, DATASRC_VALIDATE_WARNING).arg(*zone_name).arg(*rrclass).
+        arg(reason);
+}
+
+void
+logError(const dns::Name* zone_name, const dns::RRClass* rrclass,
+         const std::string& reason)
+{
+    LOG_ERROR(logger, DATASRC_VALIDATE_ERROR).arg(*zone_name).arg(*rrclass).
+        arg(reason);
+}
+
 } // end unnamed namespace
 } // end unnamed namespace
 
 
 bool
 bool
@@ -123,6 +144,19 @@ ZoneLoader::loadIncremental(size_t limit) {
     }
     }
 
 
     if (complete_) {
     if (complete_) {
+        // Everything is loaded. Perform some basic sanity checks on the zone.
+        RRsetCollection collection(updater_);
+        dns::Name zone_name(updater_->getFinder().getOrigin());
+        dns::RRClass zone_class(updater_->getFinder().getClass());
+        dns::ZoneCheckerCallbacks
+            callbacks(boost::bind(&logError, &zone_name, &zone_class, _1),
+                      boost::bind(&logWarning, &zone_name, &zone_class, _1));
+        if (!dns::checkZone(zone_name, zone_class, collection, callbacks)) {
+            // Validation failed.
+            loaded_ok_ = false;
+            isc_throw(ZoneContentError, "Errors found when validating zone " <<
+                      zone_name << "/" << zone_class);
+        }
         updater_->commit();
         updater_->commit();
     }
     }
     return (complete_);
     return (complete_);