You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2012/07/11 00:29:26 UTC

svn commit: r1359937 - in /incubator/mesos/trunk/src: tests/zookeeper_tests.cpp zookeeper/group.cpp

Author: benh
Date: Tue Jul 10 22:29:25 2012
New Revision: 1359937

URL: http://svn.apache.org/viewvc?rev=1359937&view=rev
Log:
Add functionality to create a ZooKeeper "group" even when some parent
znodes in the specified ZooKeeper path are not readable/writable using
the authentication provided but the final parent znode allows it
(contributed by John Sirois, https://reviews.apache.org/r/5869).

Modified:
    incubator/mesos/trunk/src/tests/zookeeper_tests.cpp
    incubator/mesos/trunk/src/zookeeper/group.cpp

Modified: incubator/mesos/trunk/src/tests/zookeeper_tests.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/tests/zookeeper_tests.cpp?rev=1359937&r1=1359936&r2=1359937&view=diff
==============================================================================
--- incubator/mesos/trunk/src/tests/zookeeper_tests.cpp (original)
+++ incubator/mesos/trunk/src/tests/zookeeper_tests.cpp Tue Jul 10 22:29:25 2012
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+#include <zookeeper.h>
+
 #include <string>
 
 #include <gtest/gtest.h>
@@ -366,3 +368,51 @@ TEST_F(ZooKeeperTest, MultipleGroups)
   ASSERT_TRUE(cancelled.isReady());
   ASSERT_FALSE(cancelled.get());
 }
+
+
+TEST_F(ZooKeeperTest, GroupPathWithRestrictivePerms)
+{
+  mesos::internal::test::BaseZooKeeperTest::TestWatcher watcher;
+
+  ZooKeeper authenticatedZk(zks->connectString(), NO_TIMEOUT, &watcher);
+  watcher.awaitSessionEvent(ZOO_CONNECTED_STATE);
+  authenticatedZk.authenticate("digest", "creator:creator");
+  authenticatedZk.create("/read-only",
+                         "42",
+                         zookeeper::EVERYONE_READ_CREATOR_ALL,
+                         0,
+                         NULL);
+  assertGet(&authenticatedZk, "/read-only", "42");
+  authenticatedZk.create("/read-only/writable",
+                         "37",
+                         ZOO_OPEN_ACL_UNSAFE,
+                         0,
+                         NULL);
+  assertGet(&authenticatedZk, "/read-only/writable", "37");
+
+  zookeeper::Authentication auth("digest", "non-creator:non-creator");
+
+  zookeeper::Group failedGroup1(zks->connectString(), NO_TIMEOUT,
+                                "/read-only/", auth);
+  process::Future<zookeeper::Group::Membership> failedMembership1 =
+    failedGroup1.join("fail");
+  failedMembership1.await();
+  ASSERT_TRUE(failedMembership1.isFailed());
+
+  zookeeper::Group failedGroup2(zks->connectString(), NO_TIMEOUT,
+                                "/read-only/new", auth);
+  process::Future<zookeeper::Group::Membership> failedMembership2 =
+    failedGroup2.join("fail");
+  failedMembership2.await();
+  ASSERT_TRUE(failedMembership2.isFailed());
+
+  zookeeper::Group successGroup(zks->connectString(), NO_TIMEOUT,
+                                "/read-only/writable/", auth);
+  process::Future<zookeeper::Group::Membership> successMembership =
+    successGroup.join("succeed");
+  successMembership.await();
+
+  ASSERT_FALSE(successMembership.isFailed()) << successMembership.failure();
+  ASSERT_FALSE(successMembership.isDiscarded());
+  ASSERT_TRUE(successMembership.isReady());
+}

Modified: incubator/mesos/trunk/src/zookeeper/group.cpp
URL: http://svn.apache.org/viewvc/incubator/mesos/trunk/src/zookeeper/group.cpp?rev=1359937&r1=1359936&r2=1359937&view=diff
==============================================================================
--- incubator/mesos/trunk/src/zookeeper/group.cpp (original)
+++ incubator/mesos/trunk/src/zookeeper/group.cpp Tue Jul 10 22:29:25 2012
@@ -411,7 +411,17 @@ void GroupProcess::connected(bool reconn
       if (code == ZINVALIDSTATE || (code != ZOK && zk->retryable(code))) {
         CHECK(zk->getState() != ZOO_AUTH_FAILED_STATE);
         return; // Try again later.
-      } else if (code != ZOK && code != ZNODEEXISTS) {
+      } else if (code != ZOK && code != ZNODEEXISTS && code != ZNOAUTH) {
+        // We fail all non-OK return codes except for ZNODEEXISTS and ZNOAUTH:
+        // ZNODEEXISTS says the node in the znode path we are trying to create
+        //   already exists - this is what we wanted, so we continue.
+        // ZNOAUTH says we can't write the node, but it doesn't tell us
+        //   whether the node already exists.  We take the optimistic approach
+        //   and assume the node's parent doesn't allow us to write an already
+        //   existing node.  As long as the last node in the znode path exists
+        //   (or we can create it) and we can write children to that last node,
+        //   we're good.  This condition is tested below when we're done trying
+        //   to create the znode path.
         Try<string> message = strings::format(
             "Failed to create '%s' in ZooKeeper: %s",
             prefix, zk->message(code));
@@ -422,6 +432,29 @@ void GroupProcess::connected(bool reconn
         return;
       }
     }
+
+    // Now check we have perms to write to the final znode - this is required
+    // to run the Group.
+    string result;
+    int code = zk->create(znode + "/__write_test_", "", acl,
+                          ZOO_SEQUENCE | ZOO_EPHEMERAL, &result);
+    if (code == ZINVALIDSTATE || (code != ZOK && zk->retryable(code))) {
+      CHECK(zk->getState() != ZOO_AUTH_FAILED_STATE);
+      return; // Try again later.
+    } else if (code != ZOK) {
+      Try<string> message = strings::format(
+          "Unable to write to configured group path '%s' in ZooKeeper: %s",
+          znode.c_str(), zk->message(code));
+      error = message.isSome()
+        ? message.get()
+        : "Failed to create node in ZooKeeper";
+      abort(); // Cancels everything pending.
+      return;
+    }
+
+    // Make a best-effort only attempt to clean up our write test node -
+    // it will die with our session if the attempts fails.
+    zk->remove(result, -1);
   }
 
   state = CONNECTED;